From 93626eb0aaaf3f0de511f030d5659eed0f9f8d7a Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 15:35:15 +0100 Subject: [PATCH 01/58] feat: add category dictionary and curated agencies for alerts - Introduced a new category dictionary in JSON format to manage alert categories such as missing persons, wanted suspects, travel warnings, fraud alerts, cyber advisories, and public appeals. - Added curated agencies with relevant RSS feeds for missing persons and wanted suspects, including INTERPOL, FBI, and Europol. - Implemented a new source candidates structure for future source management. - Developed a FeedDirectory component to display alerts, source health, and statistics. - Created a custom hook to fetch and manage source health data. - Established a theme utility for consistent color management across the application. - Defined TypeScript interfaces for source health data structures to ensure type safety. --- .env.example | 20 + .github/workflows/source-discovery.yml | 67 + Dockerfile.collector | 6 +- docker-compose.yml | 10 +- docker/collector-entrypoint.sh | 9 + docs/operations.md | 3 + docs/source-vetting.md | 255 ++ go.mod | 32 +- go.sum | 57 + internal/collector/app/app.go | 66 + internal/collector/app/app_test.go | 3 +- internal/collector/config/config.go | 84 +- internal/collector/dictionary/dictionary.go | 232 ++ internal/collector/discover/discover.go | 521 ++++ internal/collector/discover/discover_test.go | 196 ++ internal/collector/discover/first.go | 78 + internal/collector/discover/http.go | 45 + internal/collector/discover/humanitarian.go | 95 + internal/collector/discover/hygiene.go | 72 + internal/collector/discover/police.go | 166 ++ internal/collector/discover/probe.go | 114 + internal/collector/discover/report.go | 35 + internal/collector/discover/search_llm.go | 176 ++ internal/collector/fetch/browser.go | 69 + internal/collector/fetch/client.go | 30 +- internal/collector/fetch/client_test.go | 80 + internal/collector/fetch/fetcher.go | 22 + internal/collector/fetch/stealth.go | 189 ++ internal/collector/model/alert.go | 81 +- internal/collector/model/source.go | 31 +- internal/collector/normalize/normalize.go | 56 +- internal/collector/output/write.go | 20 +- internal/collector/output/write_test.go | 5 +- internal/collector/parse/travelwarning.go | 85 + .../collector/parse/travelwarning_test.go | 98 + internal/collector/registry/registry.go | 64 +- internal/collector/registry/registry_test.go | 33 + internal/collector/run/run.go | 368 ++- internal/collector/run/run_test.go | 213 +- internal/collector/translate/llm.go | 108 + internal/collector/translate/llm_test.go | 60 + internal/collector/vet/client.go | 117 + internal/collector/vet/client_test.go | 64 + internal/collector/vet/source.go | 178 ++ internal/collector/vet/source_test.go | 41 + internal/sourcedb/db.go | 1088 ++++++++ internal/sourcedb/db_test.go | 282 ++ internal/sourcedb/schema.sql | 161 ++ package-lock.json | 1239 +-------- package.json | 12 +- registry/category_dictionary.json | 250 ++ registry/curated_agencies.seed.json | 331 +++ registry/source_candidates.json | 4 + registry/source_registry.json | 2399 +++++------------ src/App.tsx | 342 ++- src/components/AlertFeed.tsx | 76 +- src/components/FeedDirectory.tsx | 304 +++ src/components/GlobeView.tsx | 1422 ++-------- src/components/Header.tsx | 551 +++- src/components/StatsBar.tsx | 88 +- src/hooks/useSourceHealth.ts | 49 + src/index.css | 215 +- src/lib/regions.ts | 3 + src/lib/severity.ts | 63 +- src/lib/theme.ts | 50 + src/main.tsx | 14 +- src/types/alert.ts | 3 +- src/types/source-health.ts | 41 + 68 files changed, 8860 insertions(+), 4481 deletions(-) create mode 100644 .github/workflows/source-discovery.yml create mode 100644 docs/source-vetting.md create mode 100644 go.sum create mode 100644 internal/collector/dictionary/dictionary.go create mode 100644 internal/collector/discover/discover.go create mode 100644 internal/collector/discover/discover_test.go create mode 100644 internal/collector/discover/first.go create mode 100644 internal/collector/discover/http.go create mode 100644 internal/collector/discover/humanitarian.go create mode 100644 internal/collector/discover/hygiene.go create mode 100644 internal/collector/discover/police.go create mode 100644 internal/collector/discover/probe.go create mode 100644 internal/collector/discover/report.go create mode 100644 internal/collector/discover/search_llm.go create mode 100644 internal/collector/fetch/browser.go create mode 100644 internal/collector/fetch/fetcher.go create mode 100644 internal/collector/fetch/stealth.go create mode 100644 internal/collector/parse/travelwarning.go create mode 100644 internal/collector/parse/travelwarning_test.go create mode 100644 internal/collector/translate/llm.go create mode 100644 internal/collector/translate/llm_test.go create mode 100644 internal/collector/vet/client.go create mode 100644 internal/collector/vet/client_test.go create mode 100644 internal/collector/vet/source.go create mode 100644 internal/collector/vet/source_test.go create mode 100644 internal/sourcedb/db.go create mode 100644 internal/sourcedb/db_test.go create mode 100644 internal/sourcedb/schema.sql create mode 100644 registry/category_dictionary.json create mode 100644 registry/curated_agencies.seed.json create mode 100644 registry/source_candidates.json create mode 100644 src/components/FeedDirectory.tsx create mode 100644 src/hooks/useSourceHealth.ts create mode 100644 src/lib/theme.ts create mode 100644 src/types/source-health.ts diff --git a/.env.example b/.env.example index e63a653..9868d6b 100644 --- a/.env.example +++ b/.env.example @@ -4,3 +4,23 @@ EUOSINT_SITE_ADDRESS=:80 EUOSINT_HTTP_PORT=8080 EUOSINT_HTTPS_PORT=8443 + +# Candidate crawler intake and dead-letter queue. +CANDIDATE_QUEUE_PATH=registry/source_candidates.json +REPLACEMENT_QUEUE_PATH=registry/source_dead_letter.json +SEARCH_DISCOVERY_ENABLED=false +SEARCH_DISCOVERY_MAX_TARGETS=4 +SEARCH_DISCOVERY_MAX_URLS_PER_TARGET=3 + +# Source vetting agent. +SOURCE_VETTING_ENABLED=false +SOURCE_VETTING_PROVIDER=xai +SOURCE_VETTING_BASE_URL=https://api.x.ai/v1 +SOURCE_VETTING_API_KEY= +SOURCE_VETTING_MODEL=grok-4-1-fast +SOURCE_VETTING_TEMPERATURE=0 +SOURCE_VETTING_MAX_SAMPLE_ITEMS=6 + +# Alert-level LLM gate: yes/no + English translation + category id. +ALERT_LLM_ENABLED=false +ALERT_LLM_MODEL=grok-4-1-fast diff --git a/.github/workflows/source-discovery.yml b/.github/workflows/source-discovery.yml new file mode 100644 index 0000000..05b9e88 --- /dev/null +++ b/.github/workflows/source-discovery.yml @@ -0,0 +1,67 @@ +# Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +# SPDX-License-Identifier: Apache-2.0 + +name: Source Discovery + +on: + schedule: + - cron: "0 6 * * 1" # Every Monday at 06:00 UTC + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +jobs: + discover: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + + - name: Run source discovery + run: go run ./cmd/euosint-collector --discover --discover-output discover-results.json + + - name: Check for new candidates + id: check + run: | + count=$(jq '.new_candidate_count' discover-results.json) + echo "count=$count" >> "$GITHUB_OUTPUT" + if [ "$count" -eq 0 ]; then + echo "No new source candidates found." + else + echo "Found $count new source candidates." + fi + + - name: Create PR with results + if: steps.check.outputs.count != '0' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + branch="discover/new-sources-$(date +%Y%m%d)" + git checkout -b "$branch" + git add discover-results.json + git commit -m "chore: add ${{ steps.check.outputs.count }} discovered source candidates + + Automated discovery via FIRST.org CSIRT team directory. + + Co-Authored-By: github-actions[bot] " + git push origin "$branch" + gh pr create \ + --title "Add ${{ steps.check.outputs.count }} discovered OSINT source candidates" \ + --body "## Source Discovery Results + + Found **${{ steps.check.outputs.count }}** new feed candidates via automated discovery. + + Review \`discover-results.json\` and promote worthy candidates to \`registry/source_registry.json\`. + + ## How to review + - Check each feed URL is reachable and returns valid RSS/Atom + - Verify the organization is a legitimate CSIRT or security authority + - Add geographic coordinates and reporting metadata before merging + + 🤖 Generated by weekly source discovery workflow" \ + --label "discovery" diff --git a/Dockerfile.collector b/Dockerfile.collector index 0edd46c..5afd1cd 100644 --- a/Dockerfile.collector +++ b/Dockerfile.collector @@ -5,7 +5,8 @@ FROM golang:1.25-alpine AS build WORKDIR /app -COPY go.mod ./ +COPY go.mod go.sum ./ +RUN go mod download COPY cmd ./cmd COPY internal ./internal COPY registry ./registry @@ -15,7 +16,8 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /out/euosint-collector ./c FROM alpine:3.20 -RUN apk add --no-cache ca-certificates +RUN apk add --no-cache ca-certificates chromium +ENV CHROME_PATH=/usr/bin/chromium-browser WORKDIR /app diff --git a/docker-compose.yml b/docker-compose.yml index 6f25178..e357df8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,10 +3,12 @@ services: build: context: . dockerfile: Dockerfile.collector + env_file: + - .env command: - --watch - --registry - - /app/registry/source_registry.json + - /data/sources.db - --output - /data/alerts.json - --filtered-output @@ -15,6 +17,10 @@ services: - /data/alerts-state.json - --source-health-output - /data/source-health.json + - --candidate-queue + - /data/source_candidates.json + - --replacement-queue + - /data/source_dead_letter.json environment: INTERVAL_MS: "900000" MAX_PER_SOURCE: "20" @@ -31,6 +37,8 @@ services: dockerfile: Dockerfile depends_on: - collector + env_file: + - .env environment: EUOSINT_SITE_ADDRESS: "${EUOSINT_SITE_ADDRESS:-:80}" ports: diff --git a/docker/collector-entrypoint.sh b/docker/collector-entrypoint.sh index 8db33ef..5d8bd36 100644 --- a/docker/collector-entrypoint.sh +++ b/docker/collector-entrypoint.sh @@ -19,5 +19,14 @@ seed_if_missing /app/public-defaults/alerts.json /data/alerts.json seed_if_missing /app/public-defaults/alerts-filtered.json /data/alerts-filtered.json seed_if_missing /app/public-defaults/alerts-state.json /data/alerts-state.json seed_if_missing /app/public-defaults/source-health.json /data/source-health.json +seed_if_missing /app/registry/source_candidates.json /data/source_candidates.json + +if [ ! -f /data/sources.db ]; then + euosint-collector --source-db /data/sources.db --source-db-init + euosint-collector --source-db /data/sources.db --registry /app/registry/source_registry.json --source-db-import-registry + if [ -f /app/registry/curated_agencies.seed.json ]; then + euosint-collector --source-db /data/sources.db --curated-seed /app/registry/curated_agencies.seed.json --source-db-merge-registry + fi +fi exec euosint-collector "$@" diff --git a/docs/operations.md b/docs/operations.md index 6db1814..c5ac4e9 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -74,6 +74,9 @@ If the VM only has `docker-compose`, adjust the unit commands accordingly. ## Operational Notes - The collector writes feed output into the `feed-data` volume shared with the web container. +- Discovery intake lives in [registry/source_candidates.json](/Users/alo/Development/scalytics/EUOSINT/registry/source_candidates.json). +- Dead sources are written to the terminal DLQ in `source_dead_letter.json` and are not crawled again. +- LLM-assisted source vetting is documented in [docs/source-vetting.md](/Users/alo/Development/scalytics/EUOSINT/docs/source-vetting.md). - TLS state and certificates persist in the `caddy-data` volume. - Caddy runtime state persists in the `caddy-config` volume. - Scheduled refreshes, Docker runtime, and local collection commands all run through the Go collector. diff --git a/docs/source-vetting.md b/docs/source-vetting.md new file mode 100644 index 0000000..c964764 --- /dev/null +++ b/docs/source-vetting.md @@ -0,0 +1,255 @@ + + +# Source Vetting + +## Runtime Model + +The crawler and source vetter now have separate roles: + +- `registry/source_candidates.json`: untrusted crawler intake +- `registry/sources.db`: vetted live sources only +- `registry/source_dead_letter.json`: terminal dead-letter queue, never crawled again + +Discovery reads `source_candidates.json`, probes for RSS/Atom or durable HTML listing pages, samples content, and optionally calls an LLM source vetter. Only approved sources are promoted into `sources.db`. Promoted candidates are removed from the candidate queue. + +If `SEARCH_DISCOVERY_ENABLED=true`, discovery also uses the configured OpenAI-compatible model as a narrow search accelerator. It asks for a small number of official candidate URLs for a capped set of agencies and feeds those URLs back into the same candidate queue and vetting pipeline. + +## LLM Endpoint Contract + +The source vetter uses an OpenAI-compatible `chat/completions` endpoint. It supports: + +- OpenAI +- Mistral +- xAI +- Scalytics Copilot +- Claude-compatible gateways +- Gemini-compatible gateways +- vLLM +- Ollama + +The implementation is endpoint-driven, not vendor-SDK driven. If a provider does not expose a native OpenAI-compatible endpoint, place a compatible gateway in front of it and point `SOURCE_VETTING_BASE_URL` at that gateway. + +## Search-Capable Models + +Search-capable models can be used as discovery accelerators instead of scraping public search engines directly. + +Examples: + +- xAI `grok-4-1-fast` +- Gemini fast variants +- Claude Haiku variants +- Scalytics Copilot models with search enabled + +Recommended use: + +- generate a small set of candidate URLs for a specific agency, country, or sector +- pass those URLs into the candidate queue +- let the crawler, deterministic hygiene, and source vetter decide whether they are usable + +Do not use search-capable models as direct truth sources or direct promotion sources. + +### Token-Safe Search + +Use the configured model in a narrow, token-safe way: + +- ask for a small number of candidate URLs, not a long report +- constrain by agency, country, and sector +- request only official or high-confidence source URLs +- avoid broad prompts like "find everything about police feeds worldwide" +- prefer short JSON output with URLs and a one-line reason + +Good pattern: + +- input: `Find up to 5 official feed/API/newsroom URLs for Bundeskriminalamt related to wanted suspects or public appeals. Return JSON only.` +- output: small candidate list + +Bad pattern: + +- input: `Research German law enforcement internet presence in detail and summarize everything.` + +## Environment Variables + +```dotenv +SEARCH_DISCOVERY_ENABLED=true +SEARCH_DISCOVERY_MAX_TARGETS=4 +SEARCH_DISCOVERY_MAX_URLS_PER_TARGET=3 +SOURCE_VETTING_ENABLED=true +SOURCE_VETTING_PROVIDER=xai +SOURCE_VETTING_BASE_URL=https://api.x.ai/v1 +SOURCE_VETTING_API_KEY= +SOURCE_VETTING_MODEL=grok-4-1-fast +SOURCE_VETTING_TEMPERATURE=0 +SOURCE_VETTING_MAX_SAMPLE_ITEMS=6 +ALERT_LLM_ENABLED=true +ALERT_LLM_MODEL=grok-4-1-fast +``` + +Put the real API key only in your local `.env`. Do not commit it. + +## Example Endpoints + +OpenAI: + +```dotenv +SOURCE_VETTING_PROVIDER=openai +SOURCE_VETTING_BASE_URL=https://api.openai.com/v1 +``` + +Mistral: + +```dotenv +SOURCE_VETTING_PROVIDER=mistral +SOURCE_VETTING_BASE_URL=https://api.mistral.ai/v1 +``` + +xAI: + +```dotenv +SOURCE_VETTING_PROVIDER=xai +SOURCE_VETTING_BASE_URL=https://api.x.ai/v1 +SOURCE_VETTING_MODEL=grok-4-1-fast +ALERT_LLM_MODEL=grok-4-1-fast +``` + +Scalytics Copilot: + +```dotenv +SOURCE_VETTING_PROVIDER=scalytics-copilot +SOURCE_VETTING_BASE_URL=https://YOUR_SCALYTICS_COPILOT_URL/v1 +SOURCE_VETTING_MODEL=your-copilot-model +ALERT_LLM_MODEL=your-copilot-model +``` + +vLLM: + +```dotenv +SOURCE_VETTING_PROVIDER=vllm +SOURCE_VETTING_BASE_URL=http://vllm-host:8000/v1 +SOURCE_VETTING_API_KEY=dummy +``` + +Ollama: + +```dotenv +SOURCE_VETTING_PROVIDER=ollama +SOURCE_VETTING_BASE_URL=http://localhost:11434/v1 +SOURCE_VETTING_API_KEY=dummy +``` + +Claude-compatible gateway: + +```dotenv +SOURCE_VETTING_PROVIDER=claude +SOURCE_VETTING_BASE_URL=https://your-gateway.example/v1 +``` + +Gemini-compatible gateway: + +```dotenv +SOURCE_VETTING_PROVIDER=gemini +SOURCE_VETTING_BASE_URL=https://your-gateway.example/v1 +``` + +## CLI Usage + +Run the crawler and vetter once: + +```bash +go run ./cmd/euosint-collector \ + --discover \ + --registry registry/sources.db \ + --candidate-queue registry/source_candidates.json \ + --replacement-queue registry/source_dead_letter.json \ + --search-discovery \ + --search-discovery-max-targets 4 \ + --search-discovery-max-urls 3 \ + --source-vetting \ + --source-vetting-provider xai \ + --source-vetting-base-url https://api.x.ai/v1 \ + --source-vetting-api-key "$SOURCE_VETTING_API_KEY" \ + --source-vetting-model grok-4-1-fast \ + --alert-llm \ + --alert-llm-model grok-4-1-fast +``` + +## Promotion Policy + +The LLM does not bypass deterministic hygiene. + +Sources are rejected before the LLM stage if they look like: + +- local or municipal police +- generic institutional news +- low-signal public relations pages +- sources with no sample items to assess + +Approved sources are promoted into `sources.db` with: + +- `promotion_status` +- `source_quality` +- `operational_relevance` +- `level` +- `mission_tags` + +The live watcher only loads `promotion_status = active`. + +## Alert-Level LLM Gate + +You can also enable an item-level LLM gate for RSS and HTML-list items. + +When enabled, each candidate alert item is sent to the same OpenAI-compatible endpoint with a short prompt that must return strict JSON: + +- `yes`: whether the item is intelligence-relevant or just noise +- `translation`: a short English title +- `category_id`: the normalized category id if `yes = true` + +If `yes = false`, the collector drops the item. +If `yes = true`, the collector uses the English title and category override during normalization. + +Example: + +```dotenv +ALERT_LLM_ENABLED=true +ALERT_LLM_MODEL=grok-4-1-fast +``` + +This uses the same provider/base URL/API key as source vetting. + +The same principle applies here: if your configured model supports search, use it to return a strict, short yes/no decision, a short English title, and a category id. Keep prompts short and outputs structured to avoid wasting tokens. + +Equivalent xAI request shape: + +```bash +curl https://api.x.ai/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $SOURCE_VETTING_API_KEY" \ + -d '{ + "messages": [ + {"role": "system", "content": "You are a test assistant."}, + {"role": "user", "content": "Testing. Just say hi and hello world and nothing else."} + ], + "model": "grok-4-1-fast", + "stream": false, + "temperature": 0 + }' +``` + +Equivalent Scalytics Copilot request shape: + +```bash +curl https://YOUR_SCALYTICS_COPILOT_URL/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $SOURCE_VETTING_API_KEY" \ + -d '{ + "messages": [ + {"role": "system", "content": "You are a test assistant."}, + {"role": "user", "content": "Testing. Just say hi and hello world and nothing else."} + ], + "model": "your-copilot-model", + "stream": false, + "temperature": 0 + }' +``` diff --git a/go.mod b/go.mod index 4e8c44c..defcbdb 100644 --- a/go.mod +++ b/go.mod @@ -3,4 +3,34 @@ module github.com/scalytics/euosint -go 1.25 +go 1.25.0 + +require ( + github.com/andybalholm/brotli v1.0.6 + github.com/chromedp/chromedp v0.13.6 + github.com/refraction-networking/utls v1.8.2 +) + +require ( + github.com/chromedp/cdproto v0.0.0-20250403032234-65de8f5d025b // indirect + github.com/chromedp/sysutil v1.1.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/go-json-experiment/json v0.0.0-20250211171154-1ae217ad3535 // indirect + github.com/gobwas/httphead v0.1.0 // indirect + github.com/gobwas/pool v0.2.1 // indirect + github.com/gobwas/ws v1.4.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/klauspost/compress v1.17.4 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/ncruces/go-strftime v1.0.0 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + golang.org/x/crypto v0.49.0 // indirect + golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect + golang.org/x/net v0.52.0 // indirect + golang.org/x/sys v0.42.0 // indirect + golang.org/x/text v0.35.0 // indirect + modernc.org/libc v1.67.6 // indirect + modernc.org/mathutil v1.7.1 // indirect + modernc.org/memory v1.11.0 // indirect + modernc.org/sqlite v1.46.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..4d8fbda --- /dev/null +++ b/go.sum @@ -0,0 +1,57 @@ +github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI= +github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/chromedp/cdproto v0.0.0-20250403032234-65de8f5d025b h1:jJmiCljLNTaq/O1ju9Bzz2MPpFlmiTn0F7LwCoeDZVw= +github.com/chromedp/cdproto v0.0.0-20250403032234-65de8f5d025b/go.mod h1:NItd7aLkcfOA/dcMXvl8p1u+lQqioRMq/SqDp71Pb/k= +github.com/chromedp/chromedp v0.13.6 h1:xlNunMyzS5bu3r/QKrb3fzX6ow3WBQ6oao+J65PGZxk= +github.com/chromedp/chromedp v0.13.6/go.mod h1:h8GPP6ZtLMLsU8zFbTcb7ZDGCvCy8j/vRoFmRltQx9A= +github.com/chromedp/sysutil v1.1.0 h1:PUFNv5EcprjqXZD9nJb9b/c9ibAbxiYo4exNWZyipwM= +github.com/chromedp/sysutil v1.1.0/go.mod h1:WiThHUdltqCNKGc4gaU50XgYjwjYIhKWoHGPTUfWTJ8= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/go-json-experiment/json v0.0.0-20250211171154-1ae217ad3535 h1:yE7argOs92u+sSCRgqqe6eF+cDaVhSPlioy1UkA0p/w= +github.com/go-json-experiment/json v0.0.0-20250211171154-1ae217ad3535/go.mod h1:BWmvoE1Xia34f3l/ibJweyhrT+aROb/FQ6d+37F0e2s= +github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.4.0 h1:CTaoG1tojrh4ucGPcoJFiAQUAsEWekEWvLy7GsVNqGs= +github.com/gobwas/ws v1.4.0/go.mod h1:G3gNqMNtPppf5XUz7O4shetPpcZ1VJ7zt18dlUeakrc= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo= +github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= +github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw= +github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= +github.com/refraction-networking/utls v1.8.2 h1:j4Q1gJj0xngdeH+Ox/qND11aEfhpgoEvV+S9iJ2IdQo= +github.com/refraction-networking/utls v1.8.2/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= +golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= +golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= +golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= +golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= +golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= +golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= +modernc.org/libc v1.67.6 h1:eVOQvpModVLKOdT+LvBPjdQqfrZq+pC39BygcT+E7OI= +modernc.org/libc v1.67.6/go.mod h1:JAhxUVlolfYDErnwiqaLvUqc8nfb2r6S6slAgZOnaiE= +modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= +modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= +modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= +modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= +modernc.org/sqlite v1.46.1 h1:eFJ2ShBLIEnUWlLy12raN0Z1plqmFX9Qe3rjQTKt6sU= +modernc.org/sqlite v1.46.1/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA= diff --git a/internal/collector/app/app.go b/internal/collector/app/app.go index 677066c..73fc90f 100644 --- a/internal/collector/app/app.go +++ b/internal/collector/app/app.go @@ -6,10 +6,13 @@ package app import ( "context" "flag" + "fmt" "io" "github.com/scalytics/euosint/internal/collector/config" + "github.com/scalytics/euosint/internal/collector/discover" "github.com/scalytics/euosint/internal/collector/run" + "github.com/scalytics/euosint/internal/sourcedb" ) func Run(ctx context.Context, args []string, stdout io.Writer, stderr io.Writer) error { @@ -31,6 +34,32 @@ func Run(ctx context.Context, args []string, stdout io.Writer, stderr io.Writer) fs.Float64Var(&cfg.MissingPersonRelevanceThreshold, "missing-person-threshold", cfg.MissingPersonRelevanceThreshold, "Relevance threshold for missing person alerts") fs.BoolVar(&cfg.FailOnCriticalSourceGap, "fail-on-critical-source-gap", cfg.FailOnCriticalSourceGap, "Fail the run when critical sources fetch zero records") fs.BoolVar(&cfg.TranslateEnabled, "translate", cfg.TranslateEnabled, "Translate non-Latin RSS titles and summaries to English") + fs.BoolVar(&cfg.BrowserEnabled, "browser", cfg.BrowserEnabled, "Enable headless Chrome fetching for browser-mode sources") + fs.IntVar(&cfg.BrowserTimeoutMS, "browser-timeout-ms", cfg.BrowserTimeoutMS, "Timeout in milliseconds for headless Chrome page loads") + fs.BoolVar(&cfg.DiscoverMode, "discover", cfg.DiscoverMode, "Run source discovery instead of collection") + fs.BoolVar(&cfg.DiscoverBackground, "discover-background", cfg.DiscoverBackground, "Run source discovery in the background while the collector is watching feeds") + fs.IntVar(&cfg.DiscoverIntervalMS, "discover-interval-ms", cfg.DiscoverIntervalMS, "Background discovery interval in milliseconds") + fs.StringVar(&cfg.DiscoverOutputPath, "discover-output", cfg.DiscoverOutputPath, "Path for discovery results JSON file") + fs.StringVar(&cfg.CandidateQueuePath, "candidate-queue", cfg.CandidateQueuePath, "Path for the crawler candidate intake JSON file") + fs.BoolVar(&cfg.SearchDiscoveryEnabled, "search-discovery", cfg.SearchDiscoveryEnabled, "Use the configured OpenAI-compatible model as a token-safe candidate URL discovery accelerator") + fs.IntVar(&cfg.SearchDiscoveryMaxTargets, "search-discovery-max-targets", cfg.SearchDiscoveryMaxTargets, "Maximum number of search-discovery targets per run") + fs.IntVar(&cfg.SearchDiscoveryMaxURLsPerTarget, "search-discovery-max-urls", cfg.SearchDiscoveryMaxURLsPerTarget, "Maximum number of URLs requested from the model per search target") + fs.BoolVar(&cfg.VettingEnabled, "source-vetting", cfg.VettingEnabled, "Enable LLM-assisted source vetting and promotion for discovered candidates") + fs.StringVar(&cfg.VettingProvider, "source-vetting-provider", cfg.VettingProvider, "LLM provider label for docs/logging (openai, mistral, xai, claude, gemini, vllm, ollama)") + fs.StringVar(&cfg.VettingBaseURL, "source-vetting-base-url", cfg.VettingBaseURL, "OpenAI-compatible base URL for source vetting") + fs.StringVar(&cfg.VettingAPIKey, "source-vetting-api-key", cfg.VettingAPIKey, "API key for the source vetting endpoint") + fs.StringVar(&cfg.VettingModel, "source-vetting-model", cfg.VettingModel, "Model name for the source vetting endpoint") + fs.Float64Var(&cfg.VettingTemperature, "source-vetting-temperature", cfg.VettingTemperature, "Temperature for source vetting requests") + fs.IntVar(&cfg.VettingMaxSampleItems, "source-vetting-max-samples", cfg.VettingMaxSampleItems, "Maximum sample items fetched per discovered source for vetting") + fs.BoolVar(&cfg.AlertLLMEnabled, "alert-llm", cfg.AlertLLMEnabled, "Enable LLM alert translation and yes/no category gating") + fs.StringVar(&cfg.AlertLLMModel, "alert-llm-model", cfg.AlertLLMModel, "Model name for LLM alert translation/gating") + fs.StringVar(&cfg.ReplacementQueuePath, "replacement-queue", cfg.ReplacementQueuePath, "Path for the dead-source DLQ JSON file") + fs.StringVar(&cfg.SourceDBPath, "source-db", cfg.SourceDBPath, "Path to the SQLite source database") + fs.BoolVar(&cfg.SourceDBInit, "source-db-init", cfg.SourceDBInit, "Initialize the SQLite source database schema") + fs.BoolVar(&cfg.SourceDBImportRegistry, "source-db-import-registry", cfg.SourceDBImportRegistry, "Import the JSON registry into the SQLite source database") + fs.BoolVar(&cfg.SourceDBMergeRegistry, "source-db-merge-registry", cfg.SourceDBMergeRegistry, "Merge a JSON registry or curated seed into the SQLite source database") + fs.BoolVar(&cfg.SourceDBExportRegistry, "source-db-export-registry", cfg.SourceDBExportRegistry, "Export the SQLite source database back into the JSON registry") + fs.StringVar(&cfg.CuratedSeedPath, "curated-seed", cfg.CuratedSeedPath, "Path to the curated agency seed JSON file") if err := fs.Parse(args); err != nil { return err @@ -42,5 +71,42 @@ func Run(ctx context.Context, args []string, stdout io.Writer, stderr io.Writer) default: } + if cfg.DiscoverMode { + return discover.Run(ctx, cfg, stdout, stderr) + } + if cfg.SourceDBInit || cfg.SourceDBImportRegistry || cfg.SourceDBMergeRegistry || cfg.SourceDBExportRegistry { + db, err := sourcedb.Open(cfg.SourceDBPath) + if err != nil { + return err + } + defer db.Close() + + if cfg.SourceDBInit { + if err := db.Init(ctx); err != nil { + return err + } + fmt.Fprintf(stdout, "Initialized source DB schema -> %s\n", cfg.SourceDBPath) + } + if cfg.SourceDBImportRegistry { + if err := db.ImportRegistry(ctx, cfg.RegistryPath); err != nil { + return err + } + fmt.Fprintf(stdout, "Imported registry JSON into source DB -> %s\n", cfg.SourceDBPath) + } + if cfg.SourceDBMergeRegistry { + if err := db.MergeRegistry(ctx, cfg.CuratedSeedPath); err != nil { + return err + } + fmt.Fprintf(stdout, "Merged curated seed into source DB -> %s\n", cfg.SourceDBPath) + } + if cfg.SourceDBExportRegistry { + if err := db.ExportRegistry(ctx, cfg.RegistryPath); err != nil { + return err + } + fmt.Fprintf(stdout, "Exported source DB registry -> %s\n", cfg.RegistryPath) + } + return nil + } + return run.New(stdout, stderr).Run(ctx, cfg) } diff --git a/internal/collector/app/app_test.go b/internal/collector/app/app_test.go index 78d2a94..370937a 100644 --- a/internal/collector/app/app_test.go +++ b/internal/collector/app/app_test.go @@ -26,11 +26,12 @@ func TestRunWritesOutputs(t *testing.T) { "--filtered-output", filepath.Join(dir, "filtered.json"), "--state-output", filepath.Join(dir, "state.json"), "--source-health-output", filepath.Join(dir, "health.json"), + "--replacement-queue", filepath.Join(dir, "replacement.json"), }, io.Discard, io.Discard) if err != nil { t.Fatal(err) } - for _, path := range []string{"alerts.json", "filtered.json", "state.json", "health.json"} { + for _, path := range []string{"alerts.json", "filtered.json", "state.json", "health.json", "replacement.json"} { if _, err := os.Stat(filepath.Join(dir, path)); err != nil { t.Fatalf("expected %s to be written: %v", path, err) } diff --git a/internal/collector/config/config.go b/internal/collector/config/config.go index c2f4736..494f62c 100644 --- a/internal/collector/config/config.go +++ b/internal/collector/config/config.go @@ -14,7 +14,7 @@ const ( defaultFilteredPath = "public/alerts-filtered.json" defaultStatePath = "public/alerts-state.json" defaultSourceHealthPath = "public/source-health.json" - defaultRegistryPath = "registry/source_registry.json" + defaultRegistryPath = "registry/sources.db" defaultTimeoutMS = 15000 defaultIntervalMS = 900000 defaultMaxPerSource = 20 @@ -42,6 +42,33 @@ type Config struct { MaxResponseBodyBytes int64 UserAgent string TranslateEnabled bool + BrowserEnabled bool + BrowserTimeoutMS int + DiscoverMode bool + DiscoverBackground bool + DiscoverIntervalMS int + DiscoverOutputPath string + CandidateQueuePath string + SearchDiscoveryEnabled bool + SearchDiscoveryMaxTargets int + SearchDiscoveryMaxURLsPerTarget int + VettingEnabled bool + VettingProvider string + VettingBaseURL string + VettingAPIKey string + VettingModel string + VettingTemperature float64 + VettingMaxSampleItems int + AlertLLMEnabled bool + AlertLLMModel string + CategoryDictionaryPath string + ReplacementQueuePath string + SourceDBPath string + SourceDBInit bool + SourceDBImportRegistry bool + SourceDBMergeRegistry bool + SourceDBExportRegistry bool + CuratedSeedPath string } func Default() Config { @@ -62,8 +89,34 @@ func Default() Config { IntervalMS: defaultIntervalMS, HTTPTimeoutMS: defaultTimeoutMS, MaxResponseBodyBytes: defaultMaxBodyBytes, - UserAgent: "euosint-bot/1.0", + UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36", TranslateEnabled: true, + BrowserEnabled: false, + BrowserTimeoutMS: 30000, + DiscoverMode: false, + DiscoverBackground: true, + DiscoverIntervalMS: defaultIntervalMS, + DiscoverOutputPath: "discover-results.json", + CandidateQueuePath: "registry/source_candidates.json", + SearchDiscoveryEnabled: false, + SearchDiscoveryMaxTargets: 4, + SearchDiscoveryMaxURLsPerTarget: 3, + VettingEnabled: false, + VettingProvider: "openai-compatible", + VettingBaseURL: "https://api.openai.com/v1", + VettingModel: "gpt-4.1-mini", + VettingTemperature: 0, + VettingMaxSampleItems: 6, + AlertLLMEnabled: false, + AlertLLMModel: "gpt-4.1-mini", + CategoryDictionaryPath: "registry/category_dictionary.json", + ReplacementQueuePath: "registry/source_dead_letter.json", + SourceDBPath: "registry/sources.db", + SourceDBInit: false, + SourceDBImportRegistry: false, + SourceDBMergeRegistry: false, + SourceDBExportRegistry: false, + CuratedSeedPath: "registry/curated_agencies.seed.json", } } @@ -87,6 +140,33 @@ func FromEnv() Config { cfg.MaxResponseBodyBytes = int64(envInt("MAX_RESPONSE_BODY_BYTES", int(cfg.MaxResponseBodyBytes))) cfg.UserAgent = envString("USER_AGENT", cfg.UserAgent) cfg.TranslateEnabled = envBool("TRANSLATE_ENABLED", cfg.TranslateEnabled) + cfg.BrowserEnabled = envBool("BROWSER_ENABLED", cfg.BrowserEnabled) + cfg.BrowserTimeoutMS = envInt("BROWSER_TIMEOUT_MS", cfg.BrowserTimeoutMS) + cfg.DiscoverMode = envBool("DISCOVER_MODE", cfg.DiscoverMode) + cfg.DiscoverBackground = envBool("DISCOVER_BACKGROUND", cfg.DiscoverBackground) + cfg.DiscoverIntervalMS = envInt("DISCOVER_INTERVAL_MS", cfg.DiscoverIntervalMS) + cfg.DiscoverOutputPath = envString("DISCOVER_OUTPUT_PATH", cfg.DiscoverOutputPath) + cfg.CandidateQueuePath = envString("CANDIDATE_QUEUE_PATH", cfg.CandidateQueuePath) + cfg.SearchDiscoveryEnabled = envBool("SEARCH_DISCOVERY_ENABLED", cfg.SearchDiscoveryEnabled) + cfg.SearchDiscoveryMaxTargets = envInt("SEARCH_DISCOVERY_MAX_TARGETS", cfg.SearchDiscoveryMaxTargets) + cfg.SearchDiscoveryMaxURLsPerTarget = envInt("SEARCH_DISCOVERY_MAX_URLS_PER_TARGET", cfg.SearchDiscoveryMaxURLsPerTarget) + cfg.VettingEnabled = envBool("SOURCE_VETTING_ENABLED", cfg.VettingEnabled) + cfg.VettingProvider = envString("SOURCE_VETTING_PROVIDER", cfg.VettingProvider) + cfg.VettingBaseURL = envString("SOURCE_VETTING_BASE_URL", cfg.VettingBaseURL) + cfg.VettingAPIKey = envString("SOURCE_VETTING_API_KEY", cfg.VettingAPIKey) + cfg.VettingModel = envString("SOURCE_VETTING_MODEL", cfg.VettingModel) + cfg.VettingTemperature = envFloat("SOURCE_VETTING_TEMPERATURE", cfg.VettingTemperature) + cfg.VettingMaxSampleItems = envInt("SOURCE_VETTING_MAX_SAMPLE_ITEMS", cfg.VettingMaxSampleItems) + cfg.AlertLLMEnabled = envBool("ALERT_LLM_ENABLED", cfg.AlertLLMEnabled) + cfg.AlertLLMModel = envString("ALERT_LLM_MODEL", cfg.AlertLLMModel) + cfg.CategoryDictionaryPath = envString("CATEGORY_DICTIONARY_PATH", cfg.CategoryDictionaryPath) + cfg.ReplacementQueuePath = envString("REPLACEMENT_QUEUE_PATH", cfg.ReplacementQueuePath) + cfg.SourceDBPath = envString("SOURCE_DB_PATH", cfg.SourceDBPath) + cfg.SourceDBInit = envBool("SOURCE_DB_INIT", cfg.SourceDBInit) + cfg.SourceDBImportRegistry = envBool("SOURCE_DB_IMPORT_REGISTRY", cfg.SourceDBImportRegistry) + cfg.SourceDBMergeRegistry = envBool("SOURCE_DB_MERGE_REGISTRY", cfg.SourceDBMergeRegistry) + cfg.SourceDBExportRegistry = envBool("SOURCE_DB_EXPORT_REGISTRY", cfg.SourceDBExportRegistry) + cfg.CuratedSeedPath = envString("CURATED_SEED_PATH", cfg.CuratedSeedPath) return cfg } diff --git a/internal/collector/dictionary/dictionary.go b/internal/collector/dictionary/dictionary.go new file mode 100644 index 0000000..c47fe3d --- /dev/null +++ b/internal/collector/dictionary/dictionary.go @@ -0,0 +1,232 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package dictionary + +import ( + "encoding/json" + "fmt" + "os" + "sort" + "strings" + + "github.com/scalytics/euosint/internal/collector/model" +) + +type Entry struct { + Strong []string `json:"strong"` + Weak []string `json:"weak"` + Negative []string `json:"negative"` + URLHints []string `json:"url_hints"` +} + +type CategoryDictionary struct { + Default Entry `json:"default"` + Languages map[string]Entry `json:"languages"` +} + +type Document struct { + Categories map[string]CategoryDictionary `json:"categories"` +} + +type Store struct { + doc Document +} + +func Load(path string) (*Store, error) { + data, err := os.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("read category dictionary %s: %w", path, err) + } + var doc Document + if err := json.Unmarshal(data, &doc); err != nil { + return nil, fmt.Errorf("decode category dictionary %s: %w", path, err) + } + if doc.Categories == nil { + doc.Categories = map[string]CategoryDictionary{} + } + return &Store{doc: doc}, nil +} + +func (s *Store) Match(category string, source model.RegistrySource, title string, link string) bool { + if s == nil { + return true + } + cat := s.doc.Categories[strings.ToLower(strings.TrimSpace(category))] + combined := strings.ToLower(strings.TrimSpace(title + " " + link)) + urlOnly := strings.ToLower(strings.TrimSpace(link)) + + positive := merge(cat.Default.Strong) + negative := merge(cat.Default.Negative) + urlHints := merge(cat.Default.URLHints) + for _, lang := range inferLanguages(source) { + entry, ok := cat.Languages[lang] + if !ok { + continue + } + positive = append(positive, entry.Strong...) + positive = append(positive, entry.Weak...) + negative = append(negative, entry.Negative...) + urlHints = append(urlHints, entry.URLHints...) + } + + if len(positive) == 0 && len(urlHints) == 0 && len(negative) == 0 { + return true + } + for _, term := range negative { + if contains(combined, term) { + return false + } + } + for _, term := range positive { + if contains(combined, term) { + return true + } + } + for _, term := range urlHints { + if contains(urlOnly, term) { + return true + } + } + return false +} + +func inferLanguages(source model.RegistrySource) []string { + set := map[string]struct{}{"default": {}} + for _, code := range languagesForCountry(strings.ToUpper(strings.TrimSpace(source.Source.CountryCode))) { + set[code] = struct{}{} + } + lowerFeedURL := strings.ToLower(source.FeedURL + " " + strings.Join(source.FeedURLs, " ")) + switch { + case strings.Contains(lowerFeedURL, "idiomaactual=ca"), strings.Contains(lowerFeedURL, "/_ca/"): + set["ca"] = struct{}{} + case strings.Contains(lowerFeedURL, "idiomaactual=eu"): + set["eu"] = struct{}{} + case strings.Contains(lowerFeedURL, "idiomaactual=gl"): + set["gl"] = struct{}{} + } + out := make([]string, 0, len(set)) + for code := range set { + out = append(out, code) + } + sort.Strings(out) + return out +} + +func languagesForCountry(countryCode string) []string { + switch countryCode { + case "ES", "MX", "AR", "CL", "CO", "CR", "GT", "SV", "HN", "NI", "PA", "PE", "UY", "PY", "VE", "BO", "DO", "CU", "EC": + return []string{"es"} + case "FR", "BE", "LU", "MC", "SN", "CI", "CM", "TN", "DZ", "MA": + return []string{"fr"} + case "DE", "AT": + return []string{"de"} + case "IT", "SM", "VA": + return []string{"it"} + case "PT", "BR", "AO", "MZ", "GW", "CV", "ST", "TL": + return []string{"pt"} + case "NL", "SR": + return []string{"nl"} + case "SE": + return []string{"sv"} + case "NO": + return []string{"no"} + case "DK": + return []string{"da"} + case "FI": + return []string{"fi"} + case "PL": + return []string{"pl"} + case "CZ": + return []string{"cs"} + case "SK": + return []string{"sk"} + case "SI": + return []string{"sl"} + case "HR", "BA", "RS", "ME": + return []string{"hr", "sr"} + case "RO", "MD": + return []string{"ro"} + case "HU": + return []string{"hu"} + case "LT": + return []string{"lt"} + case "LV": + return []string{"lv"} + case "EE": + return []string{"et"} + case "GR", "CY": + return []string{"el"} + case "TR": + return []string{"tr"} + case "UA": + return []string{"uk"} + case "RU", "BY", "KG": + return []string{"ru"} + case "GE": + return []string{"ka"} + case "AM": + return []string{"hy"} + case "IL": + return []string{"he"} + case "SA", "AE", "EG", "JO", "LB", "IQ", "QA", "KW", "OM", "BH": + return []string{"ar"} + case "IR": + return []string{"fa"} + case "IN": + return []string{"hi", "en"} + case "PK": + return []string{"ur", "en"} + case "BD": + return []string{"bn"} + case "LK": + return []string{"si", "ta", "en"} + case "NP": + return []string{"ne"} + case "CN": + return []string{"zh"} + case "TW": + return []string{"zh-hant", "zh"} + case "HK", "MO": + return []string{"zh-hant", "zh", "en"} + case "JP": + return []string{"ja"} + case "KR": + return []string{"ko"} + case "TH": + return []string{"th"} + case "VN": + return []string{"vi"} + case "ID": + return []string{"id"} + case "MY": + return []string{"ms", "en"} + case "PH": + return []string{"fil", "en"} + case "ZA": + return []string{"en", "af"} + case "KE", "UG", "TZ": + return []string{"sw", "en"} + default: + return nil + } +} + +func merge(values []string) []string { + out := make([]string, 0, len(values)) + for _, value := range values { + value = strings.ToLower(strings.TrimSpace(value)) + if value != "" { + out = append(out, value) + } + } + return out +} + +func contains(haystack string, needle string) bool { + needle = strings.ToLower(strings.TrimSpace(needle)) + if needle == "" { + return false + } + return strings.Contains(haystack, needle) +} diff --git a/internal/collector/discover/discover.go b/internal/collector/discover/discover.go new file mode 100644 index 0000000..33fc4ce --- /dev/null +++ b/internal/collector/discover/discover.go @@ -0,0 +1,521 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package discover + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/url" + "os" + "path/filepath" + "strings" + + "github.com/scalytics/euosint/internal/collector/config" + "github.com/scalytics/euosint/internal/collector/fetch" + "github.com/scalytics/euosint/internal/collector/model" + "github.com/scalytics/euosint/internal/collector/parse" + "github.com/scalytics/euosint/internal/collector/registry" + "github.com/scalytics/euosint/internal/collector/vet" + "github.com/scalytics/euosint/internal/sourcedb" +) + +// DiscoveredSource represents a newly discovered OSINT feed candidate. +type DiscoveredSource struct { + FeedURL string `json:"feed_url"` + FeedType string `json:"feed_type"` // "rss", "atom", or "html-list" + AuthorityType string `json:"authority_type"` // "cert", "police", "national_security", etc. + Category string `json:"suggested_category"` // suggested category for registry + OrgName string `json:"org_name"` + Country string `json:"country"` + CountryCode string `json:"country_code,omitempty"` + TeamURL string `json:"team_url"` + DiscoveredVia string `json:"discovered_via"` +} + +// Run executes the candidate crawler pipeline: reads the candidate intake JSON, +// probes each candidate for stable feeds or HTML listing pages, skips dead-letter +// entries, deduplicates against the live registry, and writes a discovery report. +func Run(ctx context.Context, cfg config.Config, stdout io.Writer, stderr io.Writer) error { + discoveryCfg := cfg + if discoveryCfg.HTTPTimeoutMS < 45000 { + discoveryCfg.HTTPTimeoutMS = 45000 + } + client := fetch.New(discoveryCfg) + var searchClient *vet.Client + var sourceVetter *vet.Vetter + if cfg.VettingEnabled { + sourceVetter = vet.New(cfg) + } + if cfg.SearchDiscoveryEnabled { + searchClient = vet.NewClient(cfg) + } + + // Load existing registry for deduplication. + existing := map[string]struct{}{} + if sources, err := registry.Load(cfg.RegistryPath); err == nil { + for _, src := range sources { + if src.FeedURL != "" { + existing[normalizeURL(src.FeedURL)] = struct{}{} + } + for _, u := range src.FeedURLs { + existing[normalizeURL(u)] = struct{}{} + } + } + } + + fmt.Fprintf(stderr, "Starting source discovery (existing registry has %d feed URLs)\n", len(existing)) + + var discovered []DiscoveredSource + dead := loadDeadLetterQueue(cfg.ReplacementQueuePath) + fmt.Fprintf(stderr, "Dead-letter queue: %d sources will be skipped\n", len(dead)) + seededCandidates, err := generateAutonomousCandidates(ctx, cfg, client, searchClient, stderr) + if err != nil { + fmt.Fprintf(stderr, "WARN autonomous candidate discovery failed: %v\n", err) + } + candidates := mergeCandidates(loadCandidateQueue(cfg.CandidateQueuePath), seededCandidates, existing, dead) + fmt.Fprintf(stderr, "Candidate queue: %d sources queued for crawl\n", len(candidates)) + remainingCandidates := make([]model.SourceCandidate, 0, len(candidates)) + promotedSources := make([]model.RegistrySource, 0) + + for _, candidate := range candidates { + if ctx.Err() != nil { + break + } + if !passesDiscoveryHygiene(candidate.AuthorityName, firstNonEmpty(candidate.BaseURL, candidate.URL), candidate.AuthorityType) { + remainingCandidates = append(remainingCandidates, candidate) + continue + } + if isDeadLettered(candidate, dead) { + continue + } + + baseURL := candidateBaseURL(candidate) + if baseURL == "" { + remainingCandidates = append(remainingCandidates, candidate) + continue + } + promotedForCandidate := false + results := ProbeFeeds(ctx, client, baseURL) + for _, r := range results { + if _, ok := existing[normalizeURL(r.FeedURL)]; ok { + continue + } + existing[normalizeURL(r.FeedURL)] = struct{}{} + found := DiscoveredSource{ + FeedURL: r.FeedURL, + FeedType: r.FeedType, + AuthorityType: candidate.AuthorityType, + Category: candidate.Category, + OrgName: candidate.AuthorityName, + Country: candidate.Country, + CountryCode: candidate.CountryCode, + TeamURL: baseURL, + DiscoveredVia: "candidate-queue", + } + discovered = append(discovered, found) + if sourceVetter == nil { + continue + } + promoted, verdict, err := vetAndPromote(ctx, cfg, client, sourceVetter, candidate, found) + if err != nil { + fmt.Fprintf(stderr, "WARN source vetting failed for %s: %v\n", found.FeedURL, err) + continue + } + if promoted != nil { + promotedSources = append(promotedSources, *promoted) + promotedForCandidate = true + fmt.Fprintf(stderr, "Promoted source %s via %s (%s)\n", promoted.Source.SourceID, cfg.VettingProvider, verdict.Reason) + } + } + if len(results) == 0 { + target := strings.TrimSpace(candidate.URL) + if target == "" { + target = baseURL + } + if _, ok := existing[normalizeURL(target)]; !ok && probeHTMLPage(ctx, client, target) { + existing[normalizeURL(target)] = struct{}{} + found := DiscoveredSource{ + FeedURL: target, + FeedType: "html-list", + AuthorityType: candidate.AuthorityType, + Category: candidate.Category, + OrgName: candidate.AuthorityName, + Country: candidate.Country, + CountryCode: candidate.CountryCode, + TeamURL: baseURL, + DiscoveredVia: "candidate-queue", + } + discovered = append(discovered, found) + if sourceVetter != nil { + promoted, verdict, err := vetAndPromote(ctx, cfg, client, sourceVetter, candidate, found) + if err != nil { + fmt.Fprintf(stderr, "WARN source vetting failed for %s: %v\n", found.FeedURL, err) + } else if promoted != nil { + promotedSources = append(promotedSources, *promoted) + promotedForCandidate = true + fmt.Fprintf(stderr, "Promoted source %s via %s (%s)\n", promoted.Source.SourceID, cfg.VettingProvider, verdict.Reason) + } + } + } + } + if !promotedForCandidate { + remainingCandidates = append(remainingCandidates, candidate) + } + } + + // Write results. + fmt.Fprintf(stderr, "Discovery finished: %d new candidates\n", len(discovered)) + if err := WriteReport(cfg.DiscoverOutputPath, discovered, len(existing), stdout); err != nil { + return err + } + if err := promoteDiscoveredSources(ctx, cfg.RegistryPath, promotedSources); err != nil { + return err + } + if err := writeCandidateQueue(cfg.CandidateQueuePath, remainingCandidates); err != nil { + return err + } + return nil +} + +func generateAutonomousCandidates(ctx context.Context, cfg config.Config, client *fetch.Client, searchClient searchCompleter, stderr io.Writer) ([]model.SourceCandidate, error) { + candidates := make([]model.SourceCandidate, 0) + var failures []string + + teams, err := FetchFIRSTTeams(ctx, client) + if err != nil { + failures = append(failures, fmt.Sprintf("FIRST.org: %v", err)) + } else { + fmt.Fprintf(stderr, "FIRST.org: fetched %d teams for candidate seeding\n", len(teams)) + for _, team := range teams { + candidates = append(candidates, model.SourceCandidate{ + URL: team.Website, + AuthorityName: team.ShortName, + AuthorityType: "cert", + Category: "cyber_advisory", + Country: team.Country, + BaseURL: team.Website, + Notes: "autonomous seed: first.org", + }) + } + } + + agencies, err := FetchPoliceAgencies(ctx, client) + if err != nil { + failures = append(failures, fmt.Sprintf("Wikidata police: %v", err)) + } else { + fmt.Fprintf(stderr, "Wikidata: fetched %d police/law-enforcement agencies for candidate seeding\n", len(agencies)) + for _, agency := range agencies { + if !passesDiscoveryHygiene(agency.Name, agency.Website, agency.AuthorityType) { + continue + } + candidates = append(candidates, model.SourceCandidate{ + URL: agency.Website, + AuthorityName: agency.Name, + AuthorityType: agency.AuthorityType, + Category: agency.Category, + Country: agency.Country, + CountryCode: agency.CountryCode, + BaseURL: agency.Website, + Notes: "autonomous seed: wikidata-police", + }) + } + } + + humOrgs, err := FetchHumanitarianOrgs(ctx, client) + if err != nil { + failures = append(failures, fmt.Sprintf("Wikidata humanitarian: %v", err)) + } else { + fmt.Fprintf(stderr, "Wikidata: fetched %d humanitarian/emergency orgs for candidate seeding\n", len(humOrgs)) + for _, org := range humOrgs { + if !passesDiscoveryHygiene(org.Name, org.Website, "public_safety_program") { + continue + } + candidates = append(candidates, model.SourceCandidate{ + URL: org.Website, + AuthorityName: org.Name, + AuthorityType: "public_safety_program", + Category: "humanitarian_security", + Country: org.Country, + CountryCode: org.CountryCode, + BaseURL: org.Website, + Notes: "autonomous seed: wikidata-humanitarian", + }) + } + } + + if len(failures) > 0 { + fmt.Fprintf(stderr, "WARN structured discovery partially failed: %s\n", strings.Join(failures, " | ")) + } + llmCandidates, err := llmSearchCandidates(ctx, cfg, searchClient, candidates) + if err != nil { + failures = append(failures, fmt.Sprintf("llm-search: %v", err)) + } else if len(llmCandidates) > 0 { + fmt.Fprintf(stderr, "LLM search discovery: generated %d candidate URLs via %s\n", len(llmCandidates), cfg.VettingProvider) + candidates = append(candidates, llmCandidates...) + } + if len(failures) > 0 { + return candidates, fmt.Errorf("%s", strings.Join(failures, " | ")) + } + return candidates, nil +} + +func mergeCandidates(existingQueue []model.SourceCandidate, discovered []model.SourceCandidate, active map[string]struct{}, dead []model.SourceReplacementCandidate) []model.SourceCandidate { + out := make([]model.SourceCandidate, 0, len(existingQueue)+len(discovered)) + seen := map[string]struct{}{} + add := func(candidate model.SourceCandidate) { + if isDeadLettered(candidate, dead) { + return + } + key := normalizeURL(firstNonEmpty(candidate.URL, candidate.BaseURL)) + if key == "" { + return + } + if _, ok := active[key]; ok { + return + } + if _, ok := seen[key]; ok { + return + } + seen[key] = struct{}{} + out = append(out, candidate) + } + for _, candidate := range existingQueue { + add(candidate) + } + for _, candidate := range discovered { + add(candidate) + } + return out +} + +func normalizeURL(u string) string { + u = strings.TrimRight(strings.TrimSpace(u), "/") + u = strings.TrimPrefix(u, "https://") + u = strings.TrimPrefix(u, "http://") + return strings.ToLower(u) +} + +func loadDeadLetterQueue(path string) []model.SourceReplacementCandidate { + raw, err := os.ReadFile(path) + if err != nil { + return nil + } + var doc model.SourceReplacementDocument + if err := json.Unmarshal(raw, &doc); err != nil { + return nil + } + return doc.Sources +} + +func loadCandidateQueue(path string) []model.SourceCandidate { + raw, err := os.ReadFile(path) + if err != nil { + return nil + } + var doc model.SourceCandidateDocument + if err := json.Unmarshal(raw, &doc); err != nil { + return nil + } + return doc.Sources +} + +func writeCandidateQueue(path string, candidates []model.SourceCandidate) error { + doc := model.SourceCandidateDocument{ + GeneratedAt: "", + Sources: candidates, + } + if doc.Sources == nil { + doc.Sources = []model.SourceCandidate{} + } + return writeJSON(path, doc) +} + +func candidateBaseURL(candidate model.SourceCandidate) string { + for _, value := range []string{candidate.BaseURL, candidate.URL} { + value = strings.TrimSpace(value) + if value == "" { + continue + } + parsed, err := url.Parse(value) + if err != nil { + continue + } + if parsed.Scheme == "" || parsed.Host == "" { + continue + } + return (&url.URL{Scheme: parsed.Scheme, Host: parsed.Host}).String() + } + return "" +} + +func isDeadLettered(candidate model.SourceCandidate, dead []model.SourceReplacementCandidate) bool { + candidateURLs := compactNormalizedURLs(candidate.URL, candidate.BaseURL) + for _, entry := range dead { + for _, deadURL := range compactNormalizedURLs(entry.FeedURL, entry.BaseURL) { + for _, candidateURL := range candidateURLs { + if candidateURL == deadURL { + return true + } + } + } + } + return false +} + +func compactNormalizedURLs(values ...string) []string { + out := make([]string, 0, len(values)) + seen := map[string]struct{}{} + for _, value := range values { + norm := normalizeURL(value) + if norm == "" { + continue + } + if _, ok := seen[norm]; ok { + continue + } + seen[norm] = struct{}{} + out = append(out, norm) + } + return out +} + +func vetAndPromote(ctx context.Context, cfg config.Config, client *fetch.Client, sourceVetter *vet.Vetter, candidate model.SourceCandidate, discovered DiscoveredSource) (*model.RegistrySource, vet.Verdict, error) { + samples, err := sampleSource(ctx, client, discovered, cfg.VettingMaxSampleItems) + if err != nil { + return nil, vet.Verdict{}, err + } + verdict, err := sourceVetter.Evaluate(ctx, vet.Input{ + AuthorityName: candidate.AuthorityName, + AuthorityType: candidate.AuthorityType, + Category: candidate.Category, + Country: candidate.Country, + CountryCode: candidate.CountryCode, + URL: discovered.FeedURL, + BaseURL: candidateBaseURL(candidate), + FeedType: discovered.FeedType, + Samples: samples, + }) + if err != nil { + return nil, vet.Verdict{}, err + } + if !verdict.Approve || verdict.PromotionStatus == "rejected" { + return nil, verdict, nil + } + + src := model.RegistrySource{ + Type: discoveredTypeToRegistryType(discovered.FeedType), + FeedURL: discovered.FeedURL, + Category: firstNonEmpty(candidate.Category, discovered.Category), + RegionTag: strings.ToUpper(strings.TrimSpace(candidate.CountryCode)), + SourceQuality: verdict.SourceQuality, + PromotionStatus: verdict.PromotionStatus, + Reporting: model.ReportingMetadata{}, + Source: model.SourceMetadata{ + SourceID: sourceIDForCandidate(candidate, discovered), + AuthorityName: firstNonEmpty(candidate.AuthorityName, discovered.OrgName), + Country: firstNonEmpty(candidate.Country, discovered.Country), + CountryCode: strings.ToUpper(firstNonEmpty(candidate.CountryCode, discovered.CountryCode)), + Region: firstNonEmpty(candidate.Region, "International"), + AuthorityType: firstNonEmpty(candidate.AuthorityType, discovered.AuthorityType, "public_safety_program"), + BaseURL: candidateBaseURL(candidate), + Scope: verdict.Level, + Level: verdict.Level, + MissionTags: verdict.MissionTags, + OperationalRelevance: verdict.OperationalRelevance, + LanguageCode: "", + }, + } + if src.Source.BaseURL == "" { + src.Source.BaseURL = discovered.TeamURL + } + return &src, verdict, nil +} + +func promoteDiscoveredSources(ctx context.Context, registryPath string, sources []model.RegistrySource) error { + if len(sources) == 0 || !isSQLitePath(registryPath) { + return nil + } + db, err := sourcedb.Open(registryPath) + if err != nil { + return fmt.Errorf("open source DB for promoted sources: %w", err) + } + defer db.Close() + if err := db.UpsertRegistrySources(ctx, sources); err != nil { + return fmt.Errorf("promote discovered sources: %w", err) + } + return nil +} + +func sampleSource(ctx context.Context, client *fetch.Client, discovered DiscoveredSource, limit int) ([]vet.Sample, error) { + accept := "application/rss+xml, application/atom+xml, application/xml, text/xml;q=0.9, */*;q=0.8" + if discovered.FeedType == "html-list" { + accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" + } + body, err := client.Text(ctx, discovered.FeedURL, true, accept) + if err != nil { + return nil, fmt.Errorf("sample source fetch %s: %w", discovered.FeedURL, err) + } + var items []parse.FeedItem + if discovered.FeedType == "html-list" { + items = parse.ParseHTMLAnchors(string(body), discovered.FeedURL) + } else { + items = parse.ParseFeed(string(body)) + } + return vet.SamplesFromFeedItems(items, limit), nil +} + +func discoveredTypeToRegistryType(feedType string) string { + switch strings.TrimSpace(feedType) { + case "html-list": + return "html-list" + default: + return "rss" + } +} + +func sourceIDForCandidate(candidate model.SourceCandidate, discovered DiscoveredSource) string { + base := firstNonEmpty(candidate.AuthorityName, discovered.OrgName, candidate.URL, discovered.FeedURL) + base = strings.ToLower(base) + replacer := strings.NewReplacer("https://", "", "http://", "", ".", "-", "/", "-", " ", "-", "_", "-", ":", "-", "&", "and") + base = replacer.Replace(base) + base = strings.Trim(base, "-") + for strings.Contains(base, "--") { + base = strings.ReplaceAll(base, "--", "-") + } + if base == "" { + return "candidate-source" + } + return base +} + +// writeJSON is a helper that marshals data to indented JSON and writes to a file. +func writeJSON(path string, data any) error { + b, err := json.MarshalIndent(data, "", " ") + if err != nil { + return err + } + b = append(b, '\n') + return os.WriteFile(path, b, 0o644) +} + +func firstNonEmpty(values ...string) string { + for _, value := range values { + value = strings.TrimSpace(value) + if value != "" { + return value + } + } + return "" +} + +func isSQLitePath(path string) bool { + switch strings.ToLower(filepath.Ext(strings.TrimSpace(path))) { + case ".db", ".sqlite", ".sqlite3": + return true + default: + return false + } +} diff --git a/internal/collector/discover/discover_test.go b/internal/collector/discover/discover_test.go new file mode 100644 index 0000000..c1f8ae5 --- /dev/null +++ b/internal/collector/discover/discover_test.go @@ -0,0 +1,196 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package discover + +import ( + "context" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/scalytics/euosint/internal/collector/config" + "github.com/scalytics/euosint/internal/collector/model" + "github.com/scalytics/euosint/internal/collector/vet" +) + +func TestDetectFeedTypeRSS(t *testing.T) { + body := `Test` + if got := detectFeedType(body); got != "rss" { + t.Errorf("expected rss, got %q", got) + } +} + +func TestDetectFeedTypeAtom(t *testing.T) { + body := `Test` + if got := detectFeedType(body); got != "atom" { + t.Errorf("expected atom, got %q", got) + } +} + +func TestDetectFeedTypeHTML(t *testing.T) { + body := `Press Releases` + if got := detectFeedType(body); got != "" { + t.Errorf("expected empty, got %q", got) + } +} + +func TestNormalizeURL(t *testing.T) { + tests := []struct { + input string + want string + }{ + {"https://www.example.com/feed/", "www.example.com/feed"}, + {"http://Example.COM/RSS", "example.com/rss"}, + {" https://foo.bar/ ", "foo.bar"}, + } + for _, tt := range tests { + got := normalizeURL(tt.input) + if got != tt.want { + t.Errorf("normalizeURL(%q) = %q, want %q", tt.input, got, tt.want) + } + } +} + +func TestCommonPressReleasePathsNotEmpty(t *testing.T) { + if len(commonPressReleasePaths) == 0 { + t.Fatal("expected non-empty press release paths") + } + for _, p := range commonPressReleasePaths { + if !strings.HasPrefix(p, "/") { + t.Errorf("press release path should start with /: %q", p) + } + } +} + +func TestPoliceAgencyQueryNotEmpty(t *testing.T) { + query := buildPoliceAgencyQuery(policeAgencyTypeIDs[:2]) + if strings.TrimSpace(query) == "" { + t.Fatal("SPARQL query should not be empty") + } + // Basic sanity — query must select the fields we parse. + for _, field := range []string{"agencyLabel", "website", "countryLabel", "countryCode"} { + if !strings.Contains(query, field) { + t.Errorf("SPARQL query missing field %q", field) + } + } +} + +func TestDiscoveryHygieneRejectsLocalPolice(t *testing.T) { + if passesDiscoveryHygiene("City of Valletta Police Department", "https://city.police.example", "police") { + t.Fatal("expected local police source to fail hygiene gate") + } + if !passesDiscoveryHygiene("Europol", "https://www.europol.europa.eu", "police") { + t.Fatal("expected supranational source to pass hygiene gate") + } +} + +func TestLoadCandidateQueueAndDeadLetterSkip(t *testing.T) { + dir := t.TempDir() + candidatePath := filepath.Join(dir, "candidates.json") + deadPath := filepath.Join(dir, "dead.json") + if err := os.WriteFile(candidatePath, []byte(`{"sources":[{"url":"https://example.test/news","authority_name":"Example Agency","authority_type":"police","category":"public_appeal","country":"France","country_code":"FR"}]}`), 0o644); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(deadPath, []byte(`{"sources":[{"feed_url":"https://example.test/news"}]}`), 0o644); err != nil { + t.Fatal(err) + } + candidates := loadCandidateQueue(candidatePath) + if len(candidates) != 1 { + t.Fatalf("expected 1 candidate, got %d", len(candidates)) + } + dead := loadDeadLetterQueue(deadPath) + if !isDeadLettered(candidates[0], dead) { + t.Fatal("expected candidate to be skipped when present in dead-letter queue") + } + if isDeadLettered(model.SourceCandidate{URL: "https://other.test/feed"}, dead) { + t.Fatal("unexpected dead-letter match for unrelated candidate") + } +} + +func TestMergeCandidatesSkipsDeadAndActive(t *testing.T) { + merged := mergeCandidates( + []model.SourceCandidate{ + {URL: "https://existing-queue.test/feed", AuthorityName: "Queued"}, + }, + []model.SourceCandidate{ + {URL: "https://active.test/feed", AuthorityName: "Active"}, + {URL: "https://dead.test/feed", AuthorityName: "Dead"}, + {URL: "https://new.test/feed", AuthorityName: "New"}, + }, + map[string]struct{}{ + normalizeURL("https://active.test/feed"): {}, + }, + []model.SourceReplacementCandidate{ + {FeedURL: "https://dead.test/feed"}, + }, + ) + if len(merged) != 2 { + t.Fatalf("expected 2 merged candidates, got %d", len(merged)) + } + if normalizeURL(merged[0].URL) != normalizeURL("https://existing-queue.test/feed") { + t.Fatalf("unexpected first merged candidate %#v", merged[0]) + } + if normalizeURL(merged[1].URL) != normalizeURL("https://new.test/feed") { + t.Fatalf("unexpected second merged candidate %#v", merged[1]) + } +} + +type stubSearchCompleter struct { + content string + err error +} + +func (s stubSearchCompleter) Complete(_ context.Context, _ []vet.Message) (string, error) { + return s.content, s.err +} + +func TestDecodeLLMSearchResponse(t *testing.T) { + resp, err := decodeLLMSearchResponse("```json\n{\"urls\":[{\"url\":\"https://www.europol.europa.eu/cms/api/rss/news\",\"reason\":\"official rss\"}]}\n```") + if err != nil { + t.Fatalf("decodeLLMSearchResponse returned error: %v", err) + } + if len(resp.URLs) != 1 || resp.URLs[0].URL != "https://www.europol.europa.eu/cms/api/rss/news" { + t.Fatalf("unexpected decoded search response: %#v", resp) + } +} + +func TestSelectSearchTargetsHonorsCap(t *testing.T) { + cfg := config.Default() + cfg.SearchDiscoveryMaxTargets = 2 + targets := selectSearchTargets(cfg, []model.SourceCandidate{ + {AuthorityName: "Europol", URL: "https://www.europol.europa.eu", AuthorityType: "police", Category: "public_appeal"}, + {AuthorityName: "Interpol", URL: "https://www.interpol.int", AuthorityType: "police", Category: "wanted_suspect"}, + {AuthorityName: "FIRST", URL: "https://www.first.org", AuthorityType: "cert", Category: "cyber_advisory"}, + }) + if len(targets) != 2 { + t.Fatalf("expected 2 search targets, got %d", len(targets)) + } +} + +func TestLLMSearchCandidatesReturnsTokenSafeCandidates(t *testing.T) { + cfg := config.Default() + cfg.SearchDiscoveryEnabled = true + cfg.SearchDiscoveryMaxTargets = 1 + cfg.SearchDiscoveryMaxURLsPerTarget = 2 + cfg.VettingProvider = "xai" + + got, err := llmSearchCandidates(context.Background(), cfg, stubSearchCompleter{ + content: `{"urls":[{"url":"https://www.europol.europa.eu/cms/api/rss/news","reason":"official rss"},{"url":"https://www.europol.europa.eu/newsroom","reason":"official newsroom"},{"url":"not-a-url","reason":"ignore"}]}`, + }, []model.SourceCandidate{ + {AuthorityName: "Europol", URL: "https://www.europol.europa.eu", AuthorityType: "police", Category: "public_appeal", Country: "Netherlands", CountryCode: "NL"}, + }) + if err != nil { + t.Fatalf("llmSearchCandidates returned error: %v", err) + } + if len(got) != 2 { + t.Fatalf("expected 2 llm-search candidates, got %d", len(got)) + } + if !strings.HasPrefix(got[0].Notes, "llm-search:xai") { + t.Fatalf("expected llm-search note, got %q", got[0].Notes) + } + if got[0].AuthorityName != "Europol" || got[0].CountryCode != "NL" { + t.Fatalf("expected metadata to be preserved, got %#v", got[0]) + } +} diff --git a/internal/collector/discover/first.go b/internal/collector/discover/first.go new file mode 100644 index 0000000..a0cde49 --- /dev/null +++ b/internal/collector/discover/first.go @@ -0,0 +1,78 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package discover + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/scalytics/euosint/internal/collector/fetch" +) + +const firstAPIBase = "https://api.first.org/data/v1/teams" +const firstPageLimit = 100 + +// FIRSTTeam represents a CSIRT team from the FIRST.org API. +type FIRSTTeam struct { + ShortName string `json:"short_name"` + Country string `json:"country"` + Website string `json:"website"` +} + +// FetchFIRSTTeams fetches all CSIRT teams from the FIRST.org API, +// paginating through all results. Returns teams that have a non-empty +// website URL. +func FetchFIRSTTeams(ctx context.Context, client *fetch.Client) ([]FIRSTTeam, error) { + var allTeams []FIRSTTeam + offset := 0 + for { + if ctx.Err() != nil { + return allTeams, ctx.Err() + } + url := fmt.Sprintf("%s?limit=%d&offset=%d", firstAPIBase, firstPageLimit, offset) + body, err := fetchTextWithRetry(ctx, client, url, "application/json") + if err != nil { + return allTeams, fmt.Errorf("FIRST.org API page offset=%d: %w", offset, err) + } + + var resp struct { + Data []struct { + ShortName string `json:"short_name"` + Country string `json:"country"` + Website string `json:"website"` + Host string `json:"host"` + } `json:"data"` + Total int `json:"total"` + } + if err := json.Unmarshal(body, &resp); err != nil { + return allTeams, fmt.Errorf("FIRST.org API parse: %w", err) + } + + for _, team := range resp.Data { + website := strings.TrimSpace(team.Website) + if website == "" { + website = strings.TrimSpace(team.Host) + } + if website == "" { + continue + } + if !strings.HasPrefix(website, "http") { + website = "https://" + website + } + allTeams = append(allTeams, FIRSTTeam{ + ShortName: team.ShortName, + Country: team.Country, + Website: strings.TrimRight(website, "/"), + }) + } + + offset += firstPageLimit + if len(resp.Data) < firstPageLimit || offset >= resp.Total { + break + } + } + return allTeams, nil +} diff --git a/internal/collector/discover/http.go b/internal/collector/discover/http.go new file mode 100644 index 0000000..d1d72b2 --- /dev/null +++ b/internal/collector/discover/http.go @@ -0,0 +1,45 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package discover + +import ( + "context" + "strings" + "time" + + "github.com/scalytics/euosint/internal/collector/fetch" +) + +func fetchTextWithRetry(ctx context.Context, client *fetch.Client, url string, accept string) ([]byte, error) { + var lastErr error + for attempt := 0; attempt < 2; attempt++ { + attemptCtx := ctx + cancel := func() {} + if _, ok := ctx.Deadline(); !ok { + attemptCtx, cancel = context.WithTimeout(ctx, 45*time.Second) + } + body, err := client.Text(attemptCtx, url, true, accept) + cancel() + if err == nil { + return body, nil + } + lastErr = err + if !looksTransient(err) || attempt == 1 { + break + } + } + return nil, lastErr +} + +func looksTransient(err error) bool { + if err == nil { + return false + } + msg := strings.ToLower(err.Error()) + return strings.Contains(msg, "timeout") || + strings.Contains(msg, "deadline exceeded") || + strings.Contains(msg, "request canceled") || + strings.Contains(msg, " eof") || + strings.Contains(msg, ": eof") +} diff --git a/internal/collector/discover/humanitarian.go b/internal/collector/discover/humanitarian.go new file mode 100644 index 0000000..d995fd3 --- /dev/null +++ b/internal/collector/discover/humanitarian.go @@ -0,0 +1,95 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package discover + +import ( + "context" + "encoding/json" + "fmt" + "net/url" + "strings" + + "github.com/scalytics/euosint/internal/collector/fetch" +) + +// HumanitarianOrg represents a humanitarian/emergency agency discovered via Wikidata. +type HumanitarianOrg struct { + Name string + Country string + CountryCode string + Website string +} + +// The SPARQL query finds humanitarian, disaster-relief, and emergency management +// agencies with official websites. Covers: +// - Emergency management agency (Q895526) +// - Humanitarian aid organization (Q15220109) +// - Disaster management (Q1460420) +// - Civil protection (Q1066476) +const humanitarianQuery = ` +SELECT ?org ?orgLabel ?website ?countryLabel ?countryCode WHERE { + VALUES ?type { + wd:Q895526 + wd:Q15220109 + wd:Q1460420 + wd:Q1066476 + } + ?org wdt:P31/wdt:P279* ?type ; + wdt:P856 ?website ; + wdt:P17 ?country . + ?country wdt:P297 ?countryCode . + SERVICE wikibase:label { bd:serviceParam wikibase:language "en" . } +} +` + +// FetchHumanitarianOrgs queries Wikidata for humanitarian, emergency management, +// and civil protection agencies worldwide. +func FetchHumanitarianOrgs(ctx context.Context, client *fetch.Client) ([]HumanitarianOrg, error) { + query := strings.TrimSpace(humanitarianQuery) + reqURL := wikidataSPARQL + "?format=json&query=" + url.QueryEscape(query) + body, err := fetchTextWithRetry(ctx, client, reqURL, "application/sparql-results+json, application/json;q=0.9") + if err != nil { + return nil, fmt.Errorf("wikidata SPARQL humanitarian: %w", err) + } + + var resp struct { + Results struct { + Bindings []struct { + OrgLabel struct{ Value string } `json:"orgLabel"` + Website struct{ Value string } `json:"website"` + CountryLabel struct{ Value string } `json:"countryLabel"` + CountryCode struct{ Value string } `json:"countryCode"` + } `json:"bindings"` + } `json:"results"` + } + if err := json.Unmarshal(body, &resp); err != nil { + return nil, fmt.Errorf("wikidata SPARQL humanitarian parse: %w", err) + } + + seen := map[string]struct{}{} + var orgs []HumanitarianOrg + for _, b := range resp.Results.Bindings { + website := strings.TrimRight(strings.TrimSpace(b.Website.Value), "/") + if website == "" { + continue + } + u, err := url.Parse(website) + if err != nil { + continue + } + host := strings.ToLower(u.Hostname()) + if _, ok := seen[host]; ok { + continue + } + seen[host] = struct{}{} + + orgs = append(orgs, HumanitarianOrg{ + Name: b.OrgLabel.Value, + Country: b.CountryLabel.Value, + CountryCode: strings.ToUpper(strings.TrimSpace(b.CountryCode.Value)), + Website: website, + }) + } + return orgs, nil +} diff --git a/internal/collector/discover/hygiene.go b/internal/collector/discover/hygiene.go new file mode 100644 index 0000000..2a918a6 --- /dev/null +++ b/internal/collector/discover/hygiene.go @@ -0,0 +1,72 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package discover + +import ( + "net/url" + "strings" +) + +var localEntityTerms = []string{ + "municipal", + "municipality", + "city of ", + "county ", + "sheriff", + "borough", + "township", + "village", + "metropolitan police", + "local police", + "police department", +} + +var genericNewsroomTerms = []string{ + "newsroom", + "press office", + "media centre", + "media center", + "communications office", +} + +func passesDiscoveryHygiene(name string, website string, authorityType string) bool { + name = strings.ToLower(strings.TrimSpace(name)) + authorityType = strings.ToLower(strings.TrimSpace(authorityType)) + if name == "" { + return false + } + for _, term := range localEntityTerms { + if strings.Contains(name, term) { + return false + } + } + if authorityType == "police" { + for _, term := range genericNewsroomTerms { + if strings.Contains(name, term) { + return false + } + } + } + if hostLooksLocal(website) { + return false + } + return true +} + +func hostLooksLocal(rawURL string) bool { + parsed, err := url.Parse(strings.TrimSpace(rawURL)) + if err != nil { + return false + } + host := strings.ToLower(parsed.Hostname()) + if host == "" { + return false + } + return strings.HasPrefix(host, "city.") || + strings.HasPrefix(host, "county.") || + strings.HasPrefix(host, "police.") || + strings.Contains(host, ".city.") || + strings.Contains(host, ".county.") || + strings.Contains(host, ".municipal.") +} diff --git a/internal/collector/discover/police.go b/internal/collector/discover/police.go new file mode 100644 index 0000000..76bf52d --- /dev/null +++ b/internal/collector/discover/police.go @@ -0,0 +1,166 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package discover + +import ( + "context" + "encoding/json" + "fmt" + "net/url" + "sort" + "strings" + + "github.com/scalytics/euosint/internal/collector/fetch" +) + +const wikidataSPARQL = "https://query.wikidata.org/sparql" + +// PoliceAgency represents a law-enforcement or national-security agency +// discovered via Wikidata whose website we should probe for feeds. +type PoliceAgency struct { + Name string + Country string + CountryCode string + Website string + AuthorityType string // "police", "national_security" + Category string // suggested registry category + PressReleasePaths []string // fallback HTML paths to probe if no RSS found +} + +// commonPressReleasePaths are subpaths frequently used by police/government +// sites for press-release listing pages. +var commonPressReleasePaths = []string{ + "/en/resources/press-releases/", + "/en/press-releases/", + "/en/news/", + "/en/media/press-releases/", + "/press-releases/", + "/news/press-releases/", + "/newsroom/press-releases/", + "/media/news/", + "/latest-news/", + "/news/", +} + +var policeAgencyTypeIDs = []string{ + "Q732717", + "Q35535", + "Q15636005", + "Q584085", + "Q1752939", + "Q12039646", +} + +func buildPoliceAgencyQuery(typeIDs []string) string { + values := make([]string, 0, len(typeIDs)) + for _, typeID := range typeIDs { + typeID = strings.TrimSpace(typeID) + if typeID == "" { + continue + } + values = append(values, "wd:"+typeID) + } + return fmt.Sprintf(` +SELECT ?agency ?agencyLabel ?website ?countryLabel ?countryCode WHERE { + VALUES ?type { %s } + ?agency wdt:P31/wdt:P279* ?type ; + wdt:P856 ?website ; + wdt:P17 ?country . + ?country wdt:P297 ?countryCode . + SERVICE wikibase:label { bd:serviceParam wikibase:language "en" . } +} +`, strings.Join(values, " ")) +} + +// FetchPoliceAgencies queries Wikidata for law-enforcement agencies +// worldwide that have official websites. This replaces a static curated +// directory and scales to every country automatically. +func FetchPoliceAgencies(ctx context.Context, client *fetch.Client) ([]PoliceAgency, error) { + // Query Wikidata in smaller chunks so one slow response does not zero out + // the entire law-enforcement directory. + seen := map[string]struct{}{} + var agencies []PoliceAgency + var failures []string + + for _, chunk := range chunkTypeIDs(policeAgencyTypeIDs, 2) { + query := strings.TrimSpace(buildPoliceAgencyQuery(chunk)) + reqURL := wikidataSPARQL + "?format=json&query=" + url.QueryEscape(query) + body, err := fetchTextWithRetry(ctx, client, reqURL, "application/sparql-results+json, application/json;q=0.9") + if err != nil { + failures = append(failures, fmt.Sprintf("%s: %v", strings.Join(chunk, ","), err)) + continue + } + + var resp struct { + Results struct { + Bindings []struct { + AgencyLabel struct{ Value string } `json:"agencyLabel"` + Website struct{ Value string } `json:"website"` + CountryLabel struct{ Value string } `json:"countryLabel"` + CountryCode struct{ Value string } `json:"countryCode"` + } `json:"bindings"` + } `json:"results"` + } + if err := json.Unmarshal(body, &resp); err != nil { + failures = append(failures, fmt.Sprintf("%s: parse: %v", strings.Join(chunk, ","), err)) + continue + } + + for _, b := range resp.Results.Bindings { + website := strings.TrimRight(strings.TrimSpace(b.Website.Value), "/") + if website == "" { + continue + } + u, err := url.Parse(website) + if err != nil { + continue + } + host := strings.ToLower(u.Hostname()) + if _, ok := seen[host]; ok { + continue + } + seen[host] = struct{}{} + + agencies = append(agencies, PoliceAgency{ + Name: b.AgencyLabel.Value, + Country: b.CountryLabel.Value, + CountryCode: strings.ToUpper(strings.TrimSpace(b.CountryCode.Value)), + Website: website, + AuthorityType: "police", + Category: "public_appeal", + PressReleasePaths: commonPressReleasePaths, + }) + } + } + + sort.Slice(agencies, func(i, j int) bool { + if agencies[i].Country != agencies[j].Country { + return agencies[i].Country < agencies[j].Country + } + return agencies[i].Name < agencies[j].Name + }) + if len(agencies) > 0 { + return agencies, nil + } + if len(failures) > 0 { + return nil, fmt.Errorf("wikidata SPARQL: %s", strings.Join(failures, " | ")) + } + return nil, nil +} + +func chunkTypeIDs(values []string, size int) [][]string { + if size <= 0 { + size = len(values) + } + var chunks [][]string + for start := 0; start < len(values); start += size { + end := start + size + if end > len(values) { + end = len(values) + } + chunk := append([]string(nil), values[start:end]...) + chunks = append(chunks, chunk) + } + return chunks +} diff --git a/internal/collector/discover/probe.go b/internal/collector/discover/probe.go new file mode 100644 index 0000000..3ffd95b --- /dev/null +++ b/internal/collector/discover/probe.go @@ -0,0 +1,114 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package discover + +import ( + "context" + "strings" + + "github.com/scalytics/euosint/internal/collector/fetch" +) + +// Common RSS/Atom feed path suffixes to probe on a website. +var feedPaths = []string{ + "/feed", + "/rss", + "/rss.xml", + "/feed.xml", + "/atom.xml", + "/.rss", + "/advisories/feed", + "/feed/rss", + "/index.xml", + // Press-release / news patterns common on police & government sites. + "/news/feed", + "/news/rss", + "/news/rss.xml", + "/en/feed", + "/en/rss", + "/en/rss.xml", + "/press-releases/feed", + "/media/news/feed", + "/resources/press-releases/feed", + "/newsroom/feed", + "/latest/feed", +} + +// ProbedFeed is a single discovered feed from probing. +type ProbedFeed struct { + FeedURL string + FeedType string // "rss" or "atom" +} + +// ProbeFeeds tries known RSS/Atom path suffixes on the given base URL and +// returns all valid feeds found (typically one, but a site may have several). +func ProbeFeeds(ctx context.Context, client *fetch.Client, baseURL string) []ProbedFeed { + baseURL = strings.TrimRight(baseURL, "/") + var found []ProbedFeed + seen := map[string]struct{}{} + for _, path := range feedPaths { + if ctx.Err() != nil { + break + } + candidate := baseURL + path + body, err := client.Text(ctx, candidate, true, "application/rss+xml, application/atom+xml, application/xml, text/xml;q=0.9, */*;q=0.8") + if err != nil { + continue + } + content := string(body) + feedType := detectFeedType(content) + if feedType == "" { + continue + } + norm := strings.ToLower(candidate) + if _, ok := seen[norm]; ok { + continue + } + seen[norm] = struct{}{} + found = append(found, ProbedFeed{FeedURL: candidate, FeedType: feedType}) + // Stop after first hit — one valid feed per site is enough. + break + } + return found +} + +// ProbeRSSFeed is a convenience wrapper that returns the first discovered +// feed URL and type (for backward compatibility). +func ProbeRSSFeed(ctx context.Context, client *fetch.Client, baseURL string) (string, string, error) { + results := ProbeFeeds(ctx, client, baseURL) + if len(results) == 0 { + return "", "", nil + } + return results[0].FeedURL, results[0].FeedType, nil +} + +// probeHTMLPage checks whether a URL returns a reachable HTML page that +// looks like a press-release listing (contains anchor tags with text). +func probeHTMLPage(ctx context.Context, client *fetch.Client, url string) bool { + body, err := client.Text(ctx, url, true, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") + if err != nil { + return false + } + content := strings.ToLower(string(body)) + // Minimal validation: must look like HTML with some links. + return strings.Contains(content, " 2048 { + prefix = prefix[:2048] + } + lower := strings.ToLower(prefix) + if strings.Contains(lower, " %s\n", + len(discovered), existingCount, outputPath) + return nil +} diff --git a/internal/collector/discover/search_llm.go b/internal/collector/discover/search_llm.go new file mode 100644 index 0000000..a308d22 --- /dev/null +++ b/internal/collector/discover/search_llm.go @@ -0,0 +1,176 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package discover + +import ( + "context" + "encoding/json" + "fmt" + "net/url" + "regexp" + "strings" + + "github.com/scalytics/euosint/internal/collector/config" + "github.com/scalytics/euosint/internal/collector/model" + "github.com/scalytics/euosint/internal/collector/vet" +) + +type searchCompleter interface { + Complete(ctx context.Context, messages []vet.Message) (string, error) +} + +type llmSearchResponse struct { + URLs []struct { + URL string `json:"url"` + Reason string `json:"reason"` + } `json:"urls"` +} + +var searchJSONBlockRe = regexp.MustCompile(`(?s)\{.*\}`) + +func llmSearchCandidates(ctx context.Context, cfg config.Config, client searchCompleter, seeds []model.SourceCandidate) ([]model.SourceCandidate, error) { + if !cfg.SearchDiscoveryEnabled || client == nil { + return nil, nil + } + targets := selectSearchTargets(cfg, seeds) + if len(targets) == 0 { + return nil, nil + } + + out := make([]model.SourceCandidate, 0, len(targets)*cfg.SearchDiscoveryMaxURLsPerTarget) + var failures []string + for _, target := range targets { + found, err := searchCandidateTarget(ctx, client, cfg, target) + if err != nil { + failures = append(failures, fmt.Sprintf("%s: %v", firstNonEmpty(target.AuthorityName, target.URL), err)) + continue + } + out = append(out, found...) + } + if len(failures) > 0 { + return out, fmt.Errorf("%s", strings.Join(failures, " | ")) + } + return out, nil +} + +func selectSearchTargets(cfg config.Config, seeds []model.SourceCandidate) []model.SourceCandidate { + maxTargets := cfg.SearchDiscoveryMaxTargets + if maxTargets <= 0 { + return nil + } + out := make([]model.SourceCandidate, 0, maxTargets) + seen := map[string]struct{}{} + for _, seed := range seeds { + if !passesDiscoveryHygiene(seed.AuthorityName, firstNonEmpty(seed.BaseURL, seed.URL), seed.AuthorityType) { + continue + } + key := strings.ToLower(strings.TrimSpace(seed.AuthorityName)) + "|" + strings.ToUpper(strings.TrimSpace(seed.CountryCode)) + "|" + strings.ToLower(strings.TrimSpace(seed.Category)) + if key == "||" { + key = normalizeURL(firstNonEmpty(seed.URL, seed.BaseURL)) + } + if key == "" { + continue + } + if _, ok := seen[key]; ok { + continue + } + seen[key] = struct{}{} + out = append(out, seed) + if len(out) >= maxTargets { + break + } + } + return out +} + +func searchCandidateTarget(ctx context.Context, client searchCompleter, cfg config.Config, target model.SourceCandidate) ([]model.SourceCandidate, error) { + maxURLs := cfg.SearchDiscoveryMaxURLsPerTarget + if maxURLs <= 0 { + maxURLs = 3 + } + + prompt := fmt.Sprintf( + "Find up to %d official or authoritative source URLs for %s in %s relevant to %s intelligence collection. Prefer RSS, Atom, JSON APIs, official newsroom feeds, or durable alert/listing pages. Reject local or municipal sources. Return strict JSON only in the form {\"urls\":[{\"url\":\"https://...\",\"reason\":\"short\"}]}.", + maxURLs, + firstNonEmpty(target.AuthorityName, "the target authority"), + firstNonEmpty(target.Country, "its jurisdiction"), + firstNonEmpty(target.Category, target.AuthorityType, "public safety"), + ) + if base := strings.TrimSpace(firstNonEmpty(target.BaseURL, target.URL)); base != "" { + prompt += " Known official website: " + base + "." + } + + content, err := client.Complete(ctx, []vet.Message{ + { + Role: "system", + Content: "You are a source discovery assistant. Return strict JSON only. Keep output short. Only list official or highly authoritative URLs likely to be usable as feeds, APIs, or durable listing pages for intelligence-relevant collection.", + }, + { + Role: "user", + Content: prompt, + }, + }) + if err != nil { + return nil, err + } + resp, err := decodeLLMSearchResponse(content) + if err != nil { + return nil, err + } + + found := make([]model.SourceCandidate, 0, len(resp.URLs)) + seen := map[string]struct{}{} + for _, item := range resp.URLs { + raw := strings.TrimSpace(item.URL) + if raw == "" { + continue + } + if !looksLikeURL(raw) { + continue + } + key := normalizeURL(raw) + if key == "" { + continue + } + if _, ok := seen[key]; ok { + continue + } + seen[key] = struct{}{} + found = append(found, model.SourceCandidate{ + URL: raw, + AuthorityName: target.AuthorityName, + AuthorityType: target.AuthorityType, + Category: target.Category, + Country: target.Country, + CountryCode: target.CountryCode, + Region: target.Region, + BaseURL: firstNonEmpty(target.BaseURL, target.URL), + Notes: "llm-search:" + strings.TrimSpace(cfg.VettingProvider) + " " + strings.TrimSpace(item.Reason), + }) + if len(found) >= maxURLs { + break + } + } + return found, nil +} + +func decodeLLMSearchResponse(content string) (llmSearchResponse, error) { + content = strings.TrimSpace(content) + if match := searchJSONBlockRe.FindString(content); match != "" { + content = match + } + var out llmSearchResponse + if err := json.Unmarshal([]byte(content), &out); err != nil { + return llmSearchResponse{}, fmt.Errorf("decode search discovery response: %w", err) + } + return out, nil +} + +func looksLikeURL(raw string) bool { + parsed, err := url.Parse(strings.TrimSpace(raw)) + if err != nil { + return false + } + return (parsed.Scheme == "https" || parsed.Scheme == "http") && parsed.Host != "" +} diff --git a/internal/collector/fetch/browser.go b/internal/collector/fetch/browser.go new file mode 100644 index 0000000..f43df90 --- /dev/null +++ b/internal/collector/fetch/browser.go @@ -0,0 +1,69 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package fetch + +import ( + "context" + "fmt" + "time" + + "github.com/chromedp/chromedp" +) + +// BrowserClient fetches page content by driving a headless Chrome instance +// via chromedp. This is used for sites that block even stealth HTTP clients +// (e.g., government sites with aggressive bot detection). +type BrowserClient struct { + allocCtx context.Context + cancelCtx context.CancelFunc + timeoutMS int +} + +// NewBrowser creates a BrowserClient with a shared headless Chrome allocator. +// Call Close() when done to release browser resources. +func NewBrowser(timeoutMS int) (*BrowserClient, error) { + opts := append(chromedp.DefaultExecAllocatorOptions[:], + chromedp.Flag("headless", true), + chromedp.Flag("no-sandbox", true), + chromedp.Flag("disable-gpu", true), + chromedp.Flag("disable-dev-shm-usage", true), + ) + allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...) + return &BrowserClient{ + allocCtx: allocCtx, + cancelCtx: cancel, + timeoutMS: timeoutMS, + }, nil +} + +// Text navigates to the URL, waits for the network to become idle, and +// returns the full page HTML as bytes. The followRedirects and accept +// parameters are accepted for interface compatibility but Chrome handles +// redirects natively and always sends its own Accept header. +func (b *BrowserClient) Text(ctx context.Context, url string, followRedirects bool, accept string) ([]byte, error) { + timeout := time.Duration(b.timeoutMS) * time.Millisecond + taskCtx, cancel := chromedp.NewContext(b.allocCtx) + defer cancel() + + taskCtx, cancelTimeout := context.WithTimeout(taskCtx, timeout) + defer cancelTimeout() + + var html string + err := chromedp.Run(taskCtx, + chromedp.Navigate(url), + chromedp.WaitReady("body"), + chromedp.OuterHTML("html", &html), + ) + if err != nil { + return nil, fmt.Errorf("browser fetch %s: %w", url, err) + } + return []byte(html), nil +} + +// Close shuts down the browser allocator and releases Chrome processes. +func (b *BrowserClient) Close() { + if b.cancelCtx != nil { + b.cancelCtx() + } +} diff --git a/internal/collector/fetch/client.go b/internal/collector/fetch/client.go index 78c3470..7fb128b 100644 --- a/internal/collector/fetch/client.go +++ b/internal/collector/fetch/client.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "io" + "net" "net/http" "strings" "time" @@ -22,8 +23,14 @@ type Client struct { } func New(cfg config.Config) *Client { + timeout := time.Duration(cfg.HTTPTimeoutMS) * time.Millisecond + return NewWithHTTPClient(cfg, &http.Client{ - Timeout: time.Duration(cfg.HTTPTimeoutMS) * time.Millisecond, + Timeout: timeout, + Transport: newStealthTransport(&net.Dialer{ + Timeout: timeout, + KeepAlive: 30 * time.Second, + }), CheckRedirect: func(req *http.Request, via []*http.Request) error { if len(via) >= 10 { return errors.New("stopped after 10 redirects") @@ -50,6 +57,16 @@ func (c *Client) Text(ctx context.Context, url string, followRedirects bool, acc if strings.TrimSpace(accept) != "" { req.Header.Set("Accept", accept) } + req.Header.Set("Accept-Language", "en-US,en;q=0.9") + req.Header.Set("Accept-Encoding", "gzip, deflate, br") + req.Header.Set("Cache-Control", "no-cache") + req.Header.Set("Pragma", "no-cache") + req.Header.Set("DNT", "1") + req.Header.Set("Upgrade-Insecure-Requests", "1") + req.Header.Set("Sec-Fetch-Dest", "document") + req.Header.Set("Sec-Fetch-Mode", "navigate") + req.Header.Set("Sec-Fetch-Site", "none") + req.Header.Set("Sec-Fetch-User", "?1") client := c.httpClient if !followRedirects { @@ -70,8 +87,7 @@ func (c *Client) Text(ctx context.Context, url string, followRedirects bool, acc return nil, fmt.Errorf("fetch %s: status %d", url, res.StatusCode) } - reader := io.LimitReader(res.Body, c.maxBodyBytes+1) - body, err := io.ReadAll(reader) + body, err := readBody(res, c.maxBodyBytes) if err != nil { return nil, fmt.Errorf("read %s: %w", url, err) } @@ -81,3 +97,11 @@ func (c *Client) Text(ctx context.Context, url string, followRedirects bool, acc return body, nil } + +// readBody reads the response body, handling gzip/br/deflate transparently. +// The stealth transport configures decompression, but if a test transport is +// injected the body may already be plain text. +func readBody(res *http.Response, limit int64) ([]byte, error) { + reader := io.LimitReader(res.Body, limit+1) + return io.ReadAll(reader) +} diff --git a/internal/collector/fetch/client_test.go b/internal/collector/fetch/client_test.go index da6b66b..c92ced5 100644 --- a/internal/collector/fetch/client_test.go +++ b/internal/collector/fetch/client_test.go @@ -4,6 +4,8 @@ package fetch import ( + "bytes" + "compress/gzip" "context" "io" "net/http" @@ -33,6 +35,84 @@ func TestClientText(t *testing.T) { } } +func TestClientTextSetsBrowserLikeHeaders(t *testing.T) { + cfg := config.Default() + client := NewWithHTTPClient(cfg, &http.Client{ + Transport: roundTripFunc(func(req *http.Request) (*http.Response, error) { + if got := req.Header.Get("User-Agent"); !strings.Contains(got, "Mozilla/5.0") { + t.Fatalf("unexpected user-agent %q", got) + } + if got := req.Header.Get("Accept-Language"); got == "" { + t.Fatal("missing Accept-Language header") + } + if got := req.Header.Get("Upgrade-Insecure-Requests"); got != "1" { + t.Fatalf("unexpected upgrade header %q", got) + } + if got := req.Header.Get("Accept-Encoding"); !strings.Contains(got, "gzip") { + t.Fatalf("missing Accept-Encoding gzip: %q", got) + } + if got := req.Header.Get("Sec-Fetch-Dest"); got != "document" { + t.Fatalf("unexpected Sec-Fetch-Dest %q", got) + } + if got := req.Header.Get("Sec-Fetch-Mode"); got != "navigate" { + t.Fatalf("unexpected Sec-Fetch-Mode %q", got) + } + return &http.Response{ + StatusCode: 200, + Body: io.NopCloser(strings.NewReader("ok")), + Header: make(http.Header), + }, nil + }), + }) + + if _, err := client.Text(context.Background(), "https://collector.test", true, "text/html"); err != nil { + t.Fatal(err) + } +} + +func TestDecompressBodyGzip(t *testing.T) { + var buf bytes.Buffer + gw := gzip.NewWriter(&buf) + gw.Write([]byte("hello gzip")) + gw.Close() + + res := &http.Response{ + StatusCode: 200, + Header: http.Header{"Content-Encoding": {"gzip"}}, + Body: io.NopCloser(&buf), + } + + if err := decompressBody(res); err != nil { + t.Fatal(err) + } + + body, err := io.ReadAll(res.Body) + if err != nil { + t.Fatal(err) + } + if string(body) != "hello gzip" { + t.Fatalf("unexpected body %q", string(body)) + } +} + +func TestDecompressBodyIdentity(t *testing.T) { + res := &http.Response{ + StatusCode: 200, + Header: make(http.Header), + Body: io.NopCloser(strings.NewReader("plain")), + } + if err := decompressBody(res); err != nil { + t.Fatal(err) + } + body, err := io.ReadAll(res.Body) + if err != nil { + t.Fatal(err) + } + if string(body) != "plain" { + t.Fatalf("unexpected body %q", string(body)) + } +} + type roundTripFunc func(*http.Request) (*http.Response, error) func (fn roundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) { diff --git a/internal/collector/fetch/fetcher.go b/internal/collector/fetch/fetcher.go new file mode 100644 index 0000000..e482f39 --- /dev/null +++ b/internal/collector/fetch/fetcher.go @@ -0,0 +1,22 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package fetch + +import "context" + +// Fetcher is the common interface for fetching page content as text. +// Both the stealth HTTP Client and the headless BrowserClient satisfy it. +type Fetcher interface { + Text(ctx context.Context, url string, followRedirects bool, accept string) ([]byte, error) +} + +// FetcherFor returns the appropriate Fetcher for the given fetch mode. +// When mode is "browser" and a BrowserClient is available, the browser +// fetcher is returned. Otherwise the stealth HTTP client is used. +func FetcherFor(mode string, client *Client, browser *BrowserClient) Fetcher { + if mode == "browser" && browser != nil { + return browser + } + return client +} diff --git a/internal/collector/fetch/stealth.go b/internal/collector/fetch/stealth.go new file mode 100644 index 0000000..bb42fd5 --- /dev/null +++ b/internal/collector/fetch/stealth.go @@ -0,0 +1,189 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package fetch + +import ( + "bufio" + "compress/flate" + "compress/gzip" + "context" + "crypto/tls" + "io" + "net" + "net/http" + "strings" + "sync" + "time" + + "github.com/andybalholm/brotli" + utls "github.com/refraction-networking/utls" + "golang.org/x/net/http2" +) + +// newStealthTransport builds an http.RoundTripper whose TLS ClientHello +// impersonates a recent Chrome release. This prevents WAFs that +// fingerprint Go's default TLS stack (JA3/JA4) from blocking requests. +// +// It supports both HTTP/1.1 and HTTP/2: after the uTLS handshake the +// negotiated ALPN protocol is cached per-host and subsequent requests +// are routed to the correct transport automatically. +// +// It also transparently decompresses gzip/br/deflate responses, since we +// explicitly send Accept-Encoding to look like a real browser (which +// disables Go's automatic gzip handling). +func newStealthTransport(dialer *net.Dialer) http.RoundTripper { + dt := &dualProtoTransport{ + dialer: dialer, + protoByHost: make(map[string]string), + } + + dt.h1 = &http.Transport{ + Proxy: http.ProxyFromEnvironment, + ForceAttemptHTTP2: false, + MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + DialTLSContext: dt.dialTLS, + DialContext: dialer.DialContext, + } + + dt.h2 = &http2.Transport{ + DialTLSContext: func(ctx context.Context, network, addr string, _ *tls.Config) (net.Conn, error) { + return dt.dialTLS(ctx, network, addr) + }, + } + + return &stealthRoundTripper{dual: dt} +} + +// dualProtoTransport manages uTLS connections and routes them to the +// appropriate HTTP/1.1 or HTTP/2 transport based on ALPN negotiation. +type dualProtoTransport struct { + dialer *net.Dialer + h1 *http.Transport + h2 *http2.Transport + + mu sync.Mutex + protoByHost map[string]string // hostname -> "h2" | "h1" +} + +func (dt *dualProtoTransport) dialTLS(ctx context.Context, network, addr string) (net.Conn, error) { + rawConn, err := dt.dialer.DialContext(ctx, network, addr) + if err != nil { + return nil, err + } + + host, _, err := net.SplitHostPort(addr) + if err != nil { + host = addr + } + + tlsConn := utls.UClient(rawConn, &utls.Config{ + ServerName: host, + }, utls.HelloChrome_Auto) + + if err := tlsConn.HandshakeContext(ctx); err != nil { + rawConn.Close() + return nil, err + } + + // Cache the negotiated protocol so future requests skip the probe. + proto := tlsConn.ConnectionState().NegotiatedProtocol + dt.mu.Lock() + if proto == "h2" { + dt.protoByHost[host] = "h2" + } else { + dt.protoByHost[host] = "h1" + } + dt.mu.Unlock() + + return tlsConn, nil +} + +func (dt *dualProtoTransport) getProto(host string) string { + dt.mu.Lock() + defer dt.mu.Unlock() + return dt.protoByHost[host] +} + +// stealthRoundTripper routes requests to the appropriate protocol +// transport and transparently decompresses response bodies. +type stealthRoundTripper struct { + dual *dualProtoTransport +} + +func (s *stealthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + host := req.URL.Hostname() + proto := s.dual.getProto(host) + + var res *http.Response + var err error + + switch proto { + case "h2": + res, err = s.dual.h2.RoundTrip(req) + case "h1": + res, err = s.dual.h1.RoundTrip(req) + default: + // Unknown host — try h1 first. If the server negotiates h2 via + // ALPN, the h1 transport will fail with "malformed HTTP response" + // because it tries HTTP/1.1 framing on an h2 connection. The + // dialTLS callback caches the negotiated proto regardless, so we + // can detect this and retry with the h2 transport. + res, err = s.dual.h1.RoundTrip(req) + if err != nil && s.dual.getProto(host) == "h2" { + res, err = s.dual.h2.RoundTrip(req) + } + } + + if err != nil { + return nil, err + } + if derr := decompressBody(res); derr != nil { + // If decompression setup fails, still return the raw body. + res.Body = io.NopCloser(bufio.NewReader(res.Body)) + } + return res, nil +} + +// decompressBody wraps the response body reader to handle Content-Encoding. +func decompressBody(res *http.Response) error { + ce := strings.ToLower(strings.TrimSpace(res.Header.Get("Content-Encoding"))) + if ce == "" || ce == "identity" { + return nil + } + + var reader io.ReadCloser + switch ce { + case "gzip": + gr, err := gzip.NewReader(res.Body) + if err != nil { + return err + } + reader = gr + case "br": + reader = io.NopCloser(brotli.NewReader(res.Body)) + case "deflate": + reader = flate.NewReader(res.Body) + default: + return nil + } + + original := res.Body + res.Body = &wrappedBody{reader: reader, closer: original} + res.Header.Del("Content-Encoding") + res.Header.Del("Content-Length") + return nil +} + +// wrappedBody reads from the decompressor but closes the underlying conn. +type wrappedBody struct { + reader io.ReadCloser + closer io.Closer +} + +func (w *wrappedBody) Read(p []byte) (int, error) { return w.reader.Read(p) } +func (w *wrappedBody) Close() error { + w.reader.Close() + return w.closer.Close() +} diff --git a/internal/collector/model/alert.go b/internal/collector/model/alert.go index 73fd02f..d8ba158 100644 --- a/internal/collector/model/alert.go +++ b/internal/collector/model/alert.go @@ -50,26 +50,69 @@ type DuplicateAudit struct { } type SourceHealthEntry struct { - SourceID string `json:"source_id"` - AuthorityName string `json:"authority_name"` - Type string `json:"type"` - Status string `json:"status"` - FetchedCount int `json:"fetched_count"` - FeedURL string `json:"feed_url"` - Error string `json:"error,omitempty"` - StartedAt string `json:"started_at"` - FinishedAt string `json:"finished_at"` - ActiveCount int `json:"active_count,omitempty"` - FilteredCount int `json:"filtered_count,omitempty"` + SourceID string `json:"source_id"` + AuthorityName string `json:"authority_name"` + Type string `json:"type"` + Status string `json:"status"` + FetchedCount int `json:"fetched_count"` + FeedURL string `json:"feed_url"` + Error string `json:"error,omitempty"` + ErrorClass string `json:"error_class,omitempty"` + NeedsReplacement bool `json:"needs_replacement,omitempty"` + DiscoveryAction string `json:"discovery_action,omitempty"` + StartedAt string `json:"started_at"` + FinishedAt string `json:"finished_at"` + ActiveCount int `json:"active_count,omitempty"` + FilteredCount int `json:"filtered_count,omitempty"` +} + +type SourceReplacementCandidate struct { + SourceID string `json:"source_id"` + AuthorityName string `json:"authority_name"` + Type string `json:"type"` + FeedURL string `json:"feed_url"` + BaseURL string `json:"base_url,omitempty"` + Country string `json:"country,omitempty"` + CountryCode string `json:"country_code,omitempty"` + Region string `json:"region,omitempty"` + AuthorityType string `json:"authority_type,omitempty"` + Category string `json:"category,omitempty"` + Error string `json:"error,omitempty"` + ErrorClass string `json:"error_class,omitempty"` + DiscoveryAction string `json:"discovery_action,omitempty"` + LastAttemptAt string `json:"last_attempt_at,omitempty"` } type SourceHealthDocument struct { - GeneratedAt string `json:"generated_at"` - CriticalSourcePrefixes []string `json:"critical_source_prefixes"` - FailOnCriticalSourceGap bool `json:"fail_on_critical_source_gap"` - TotalSources int `json:"total_sources"` - SourcesOK int `json:"sources_ok"` - SourcesError int `json:"sources_error"` - DuplicateAudit DuplicateAudit `json:"duplicate_audit"` - Sources []SourceHealthEntry `json:"sources"` + GeneratedAt string `json:"generated_at"` + CriticalSourcePrefixes []string `json:"critical_source_prefixes"` + FailOnCriticalSourceGap bool `json:"fail_on_critical_source_gap"` + TotalSources int `json:"total_sources"` + SourcesOK int `json:"sources_ok"` + SourcesError int `json:"sources_error"` + DuplicateAudit DuplicateAudit `json:"duplicate_audit"` + ReplacementQueue []SourceReplacementCandidate `json:"replacement_queue"` + Sources []SourceHealthEntry `json:"sources"` +} + +type SourceReplacementDocument struct { + GeneratedAt string `json:"generated_at"` + Sources []SourceReplacementCandidate `json:"sources"` +} + +type SourceCandidate struct { + URL string `json:"url"` + AuthorityName string `json:"authority_name,omitempty"` + AuthorityType string `json:"authority_type,omitempty"` + Category string `json:"category,omitempty"` + Country string `json:"country,omitempty"` + CountryCode string `json:"country_code,omitempty"` + Region string `json:"region,omitempty"` + BaseURL string `json:"base_url,omitempty"` + Notes string `json:"notes,omitempty"` +} + +type SourceCandidateDocument struct { + GeneratedAt string `json:"generated_at,omitempty"` + Sources []SourceCandidate `json:"sources"` } diff --git a/internal/collector/model/source.go b/internal/collector/model/source.go index 6e35c80..1abb519 100644 --- a/internal/collector/model/source.go +++ b/internal/collector/model/source.go @@ -3,8 +3,11 @@ package model +// Supported source types: rss, html-list, kev-json, interpol-red-json, +// interpol-yellow-json, travelwarning-json, travelwarning-atom. type RegistrySource struct { Type string `json:"type"` + FetchMode string `json:"fetch_mode,omitempty"` // "stealth" (default) or "browser" FollowRedirects bool `json:"followRedirects"` FeedURL string `json:"feed_url"` FeedURLs []string `json:"feed_urls,omitempty"` @@ -15,6 +18,11 @@ type RegistrySource struct { MaxItems int `json:"max_items"` IncludeKeywords []string `json:"include_keywords,omitempty"` ExcludeKeywords []string `json:"exclude_keywords,omitempty"` + SourceQuality float64 `json:"source_quality,omitempty"` + PromotionStatus string `json:"promotion_status,omitempty"` + RejectionReason string `json:"rejection_reason,omitempty"` + IsMirror bool `json:"is_mirror,omitempty"` + PreferredRank int `json:"preferred_source_rank,omitempty"` Reporting ReportingMetadata `json:"reporting"` Source SourceMetadata `json:"source"` } @@ -27,11 +35,20 @@ type ReportingMetadata struct { } type SourceMetadata struct { - SourceID string `json:"source_id"` - AuthorityName string `json:"authority_name"` - Country string `json:"country"` - CountryCode string `json:"country_code"` - Region string `json:"region"` - AuthorityType string `json:"authority_type"` - BaseURL string `json:"base_url"` + SourceID string `json:"source_id"` + AuthorityName string `json:"authority_name"` + Country string `json:"country"` + CountryCode string `json:"country_code"` + Region string `json:"region"` + AuthorityType string `json:"authority_type"` + BaseURL string `json:"base_url"` + Scope string `json:"scope,omitempty"` + Level string `json:"level,omitempty"` + ParentAgencyID string `json:"parent_agency_id,omitempty"` + JurisdictionName string `json:"jurisdiction_name,omitempty"` + MissionTags []string `json:"mission_tags,omitempty"` + OperationalRelevance float64 `json:"operational_relevance,omitempty"` + IsCurated bool `json:"is_curated,omitempty"` + IsHighValue bool `json:"is_high_value,omitempty"` + LanguageCode string `json:"language_code,omitempty"` } diff --git a/internal/collector/normalize/normalize.go b/internal/collector/normalize/normalize.go index 8875cf0..0b54ebb 100644 --- a/internal/collector/normalize/normalize.go +++ b/internal/collector/normalize/normalize.go @@ -49,6 +49,13 @@ var ( regexp.MustCompile(`(?i)\b(?:ceremony|speech|statement|newsletter|weekly roundup)\b`), regexp.MustCompile(`(?i)\b(?:partnership|memorandum|mou|initiative|campaign)\b`), } + certificationPatterns = []*regexp.Regexp{ + regexp.MustCompile(`(?i)\b(?:certification|certifi(?:ed|cate)|accreditation|compliance audit|standard(?:s)?)\b`), + regexp.MustCompile(`(?i)\b(?:NESAS|common criteria|ISO[\s-]?27001|ISO[\s-]?15408|ITSEC|protection profile)\b`), + regexp.MustCompile(`(?i)\b(?:evaluation|scheme|approval|conformity|audit report|test report)\b`), + regexp.MustCompile(`(?i)\b(?:product certification|vendor certification|zertifizierung|anerkennung)\b`), + regexp.MustCompile(`(?i)\b(?:training|course|curriculum|e-learning|online.?training|skill|qualification)\b`), + } securityContextPatterns = []*regexp.Regexp{ regexp.MustCompile(`(?i)\b(?:cyber|cybersecurity|infosec|information security|it security)\b`), regexp.MustCompile(`(?i)\b(?:security posture|security controls?|threat intelligence)\b`), @@ -192,6 +199,40 @@ func InterpolAlert(ctx Context, meta model.RegistrySource, title string, link st return &alert } +func TravelWarningAlert(ctx Context, meta model.RegistrySource, item parse.FeedItem) *model.Alert { + publishedAt := parseDate(item.Published) + if publishedAt.IsZero() { + publishedAt = ctx.Now + } + if !isFresh(ctx.Config, publishedAt, ctx.Now) { + return nil + } + alert := baseAlert(ctx, meta, item.Title, item.Link, publishedAt) + alert.Severity = inferTravelWarningSeverity(item.Title, item.Summary, item.Tags) + triage := score(ctx.Config, alert, FeedContext{ + Summary: item.Summary, + Author: item.Author, + Tags: item.Tags, + FeedType: meta.Type, + }) + alert.Triage = triage + return &alert +} + +func inferTravelWarningSeverity(title, summary string, tags []string) string { + text := strings.ToLower(title + " " + summary + " " + strings.Join(tags, " ")) + switch { + case containsAny(text, "do not travel", "reisewarnung", "advise against all travel", "level 4"): + return "critical" + case containsAny(text, "reconsider travel", "avoid non-essential travel", "advise against all but essential travel", "level 3", "teilreisewarnung"): + return "high" + case containsAny(text, "exercise increased caution", "exercise a high degree of caution", "level 2"): + return "medium" + default: + return "medium" + } +} + func StaticInterpolEntry(now time.Time) model.Alert { return model.Alert{ AlertID: "interpol-hub-static", @@ -278,6 +319,8 @@ func score(cfg config.Config, alert model.Alert, feed FeedContext) *model.Triage add(0.07, "education and digital capacity category") case "fraud_alert": add(0.07, "fraud incident category") + case "travel_warning": + add(0.08, "travel warning category") } hasTechnical := hasAny(text, technicalSignalPatterns) @@ -286,6 +329,7 @@ func score(cfg config.Config, alert model.Alert, feed FeedContext) *model.Triage hasSpecificImpact := hasAny(text, impactSpecificityPatterns) hasNarrative := hasAny(text, narrativePatterns) hasGeneral := hasAny(text, generalNewsPatterns) + hasCertification := hasAny(text, certificationPatterns) looksLikeBlog := isBlog(alert) if hasTechnical { @@ -309,6 +353,9 @@ func score(cfg config.Config, alert model.Alert, feed FeedContext) *model.Triage if looksLikeBlog { add(-0.10, "blog-style structure") } + if hasCertification && !hasIncident && !hasTechnical { + add(-0.22, "certification/training/standards content") + } if !hasTechnical && !hasIncident && (hasNarrative || hasGeneral) { add(-0.08, "weak incident evidence relative to narrative cues") } @@ -376,6 +423,8 @@ func defaultSeverity(category string) string { return "critical" case "public_appeal", "humanitarian_tasking", "humanitarian_security", "private_sector": return "high" + case "travel_warning": + return "high" default: return "medium" } @@ -384,9 +433,9 @@ func defaultSeverity(category string) string { func inferSeverity(title string, fallback string) string { t := strings.ToLower(title) switch { - case containsAny(t, "critical", "emergency", "zero-day", "0-day", "ransomware", "actively exploited", "exploitation", "breach", "data leak", "crypto heist", "million stolen", "wanted", "fugitive", "murder", "homicide", "missing", "amber alert", "kidnap"): + case containsAny(t, "critical", "emergency", "zero-day", "0-day", "ransomware", "actively exploited", "exploitation", "breach", "data leak", "crypto heist", "million stolen", "wanted", "fugitive", "murder", "homicide", "missing", "amber alert", "kidnap", "do not travel"): return "critical" - case containsAny(t, "hack", "compromise", "vulnerability", "high", "severe", "urgent", "fatal", "death", "shooting", "fraud", "scam", "phishing"): + case containsAny(t, "hack", "compromise", "vulnerability", "high", "severe", "urgent", "fatal", "death", "shooting", "fraud", "scam", "phishing", "reconsider travel", "avoid non-essential travel"): return "high" case containsAny(t, "arrested", "charged", "sentenced", "medium", "moderate"): return "medium" @@ -442,6 +491,9 @@ func inferPublicationType(alert model.Alert, feedType string) string { if feedType == "kev-json" || feedType == "interpol-red-json" || feedType == "interpol-yellow-json" { return "structured_incident_feed" } + if feedType == "travelwarning-json" || feedType == "travelwarning-atom" { + return "official_update" + } return "official_update" } diff --git a/internal/collector/output/write.go b/internal/collector/output/write.go index c88e7c5..91ce593 100644 --- a/internal/collector/output/write.go +++ b/internal/collector/output/write.go @@ -14,8 +14,8 @@ import ( "github.com/scalytics/euosint/internal/collector/model" ) -func Write(cfg config.Config, active []model.Alert, filtered []model.Alert, state []model.Alert, sourceHealth []model.SourceHealthEntry, duplicateAudit model.DuplicateAudit) error { - paths := []string{cfg.OutputPath, cfg.FilteredOutputPath, cfg.StateOutputPath, cfg.SourceHealthOutputPath} +func Write(cfg config.Config, active []model.Alert, filtered []model.Alert, state []model.Alert, sourceHealth []model.SourceHealthEntry, duplicateAudit model.DuplicateAudit, replacementQueue []model.SourceReplacementCandidate) error { + paths := []string{cfg.OutputPath, cfg.FilteredOutputPath, cfg.StateOutputPath, cfg.SourceHealthOutputPath, cfg.ReplacementQueuePath} for _, path := range paths { if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { return err @@ -38,9 +38,23 @@ func Write(cfg config.Config, active []model.Alert, filtered []model.Alert, stat SourcesOK: countStatus(sourceHealth, "ok"), SourcesError: countStatus(sourceHealth, "error"), DuplicateAudit: duplicateAudit, + ReplacementQueue: replacementQueue, Sources: sourceHealth, } - return writeJSON(cfg.SourceHealthOutputPath, doc) + if doc.ReplacementQueue == nil { + doc.ReplacementQueue = []model.SourceReplacementCandidate{} + } + if err := writeJSON(cfg.SourceHealthOutputPath, doc); err != nil { + return err + } + queueDoc := model.SourceReplacementDocument{ + GeneratedAt: doc.GeneratedAt, + Sources: replacementQueue, + } + if queueDoc.Sources == nil { + queueDoc.Sources = []model.SourceReplacementCandidate{} + } + return writeJSON(cfg.ReplacementQueuePath, queueDoc) } func writeJSON(path string, value any) error { diff --git a/internal/collector/output/write_test.go b/internal/collector/output/write_test.go index bde54c6..6a257fb 100644 --- a/internal/collector/output/write_test.go +++ b/internal/collector/output/write_test.go @@ -19,12 +19,13 @@ func TestWriteOutputs(t *testing.T) { cfg.FilteredOutputPath = filepath.Join(dir, "filtered.json") cfg.StateOutputPath = filepath.Join(dir, "state.json") cfg.SourceHealthOutputPath = filepath.Join(dir, "health.json") + cfg.ReplacementQueuePath = filepath.Join(dir, "replacement.json") - err := Write(cfg, []model.Alert{{AlertID: "a"}}, []model.Alert{{AlertID: "b"}}, []model.Alert{{AlertID: "c"}}, []model.SourceHealthEntry{{SourceID: "s", Status: "ok"}}, model.DuplicateAudit{}) + err := Write(cfg, []model.Alert{{AlertID: "a"}}, []model.Alert{{AlertID: "b"}}, []model.Alert{{AlertID: "c"}}, []model.SourceHealthEntry{{SourceID: "s", Status: "ok"}}, model.DuplicateAudit{}, nil) if err != nil { t.Fatal(err) } - for _, path := range []string{cfg.OutputPath, cfg.FilteredOutputPath, cfg.StateOutputPath, cfg.SourceHealthOutputPath} { + for _, path := range []string{cfg.OutputPath, cfg.FilteredOutputPath, cfg.StateOutputPath, cfg.SourceHealthOutputPath, cfg.ReplacementQueuePath} { if _, err := os.Stat(path); err != nil { t.Fatalf("expected output file %s: %v", path, err) } diff --git a/internal/collector/parse/travelwarning.go b/internal/collector/parse/travelwarning.go new file mode 100644 index 0000000..ea84839 --- /dev/null +++ b/internal/collector/parse/travelwarning.go @@ -0,0 +1,85 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package parse + +import ( + "encoding/json" + "strings" +) + +// ParseGermanAATravelWarnings parses the JSON response from the German +// Auswärtiges Amt (Federal Foreign Office) travel warning open-data API. +// The API returns an object whose keys are numeric country IDs and values +// contain the warning metadata. +func ParseGermanAATravelWarnings(body []byte) ([]FeedItem, error) { + // The top-level structure wraps a "response" object whose keys are + // country IDs mapping to warning objects, or it can be a flat map. + // We try both shapes. + var envelope struct { + Response map[string]json.RawMessage `json:"response"` + } + warnings := map[string]json.RawMessage{} + if err := json.Unmarshal(body, &envelope); err == nil && len(envelope.Response) > 0 { + warnings = envelope.Response + } else { + // Fall back to flat map keyed by country ID. + if err := json.Unmarshal(body, &warnings); err != nil { + return nil, err + } + } + + type warningEntry struct { + Title string `json:"title"` + Country string `json:"country"` + Warning string `json:"warning"` + Severity string `json:"severity"` + LastChanged string `json:"lastChanged"` + URL string `json:"url"` + Effective string `json:"effective"` + Content string `json:"content"` + } + + items := make([]FeedItem, 0, len(warnings)) + for _, raw := range warnings { + var entry warningEntry + if err := json.Unmarshal(raw, &entry); err != nil { + continue + } + title := firstNonEmpty(entry.Title, entry.Country) + if strings.TrimSpace(title) == "" { + continue + } + link := strings.TrimSpace(entry.URL) + if link == "" { + link = "https://www.auswaertiges-amt.de/de/ReiseUndSicherheit/reise-und-sicherheitshinweise" + } + summary := firstNonEmpty(entry.Warning, entry.Content) + published := firstNonEmpty(entry.LastChanged, entry.Effective) + + tags := []string{} + if entry.Severity != "" { + tags = append(tags, entry.Severity) + } + if entry.Country != "" { + tags = append(tags, entry.Country) + } + + items = append(items, FeedItem{ + Title: title, + Link: link, + Published: published, + Summary: summary, + Tags: tags, + }) + } + return items, nil +} + +// ParseFCDOAtom parses a UK FCDO (Foreign, Commonwealth & Development Office) +// Atom feed containing travel advice entries. This delegates to the generic +// Atom parser in ParseFeed and returns the results. +func ParseFCDOAtom(body []byte) ([]FeedItem, error) { + items := ParseFeed(string(body)) + return items, nil +} diff --git a/internal/collector/parse/travelwarning_test.go b/internal/collector/parse/travelwarning_test.go new file mode 100644 index 0000000..f144a48 --- /dev/null +++ b/internal/collector/parse/travelwarning_test.go @@ -0,0 +1,98 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package parse + +import ( + "testing" +) + +func TestParseGermanAATravelWarnings(t *testing.T) { + body := []byte(`{ + "1": { + "title": "Afghanistan - Reisewarnung", + "country": "Afghanistan", + "warning": "Do not travel to Afghanistan.", + "severity": "Reisewarnung", + "lastChanged": "2026-01-15", + "url": "https://www.auswaertiges-amt.de/de/aussenpolitik/laender/afghanistan-node/afghanistansicherheit/204692" + }, + "2": { + "title": "France - Exercise normal safety precautions", + "country": "France", + "warning": "No specific warnings.", + "severity": "", + "lastChanged": "2026-02-01", + "url": "https://www.auswaertiges-amt.de/de/aussenpolitik/laender/frankreich-node" + } + }`) + items, err := ParseGermanAATravelWarnings(body) + if err != nil { + t.Fatal(err) + } + if len(items) != 2 { + t.Fatalf("expected 2 items, got %d", len(items)) + } + foundAfghan := false + for _, item := range items { + if item.Title == "Afghanistan - Reisewarnung" { + foundAfghan = true + if item.Summary != "Do not travel to Afghanistan." { + t.Errorf("unexpected summary: %s", item.Summary) + } + if item.Published != "2026-01-15" { + t.Errorf("unexpected published: %s", item.Published) + } + } + } + if !foundAfghan { + t.Error("did not find Afghanistan entry") + } +} + +func TestParseGermanAATravelWarningsEnvelope(t *testing.T) { + body := []byte(`{"response": { + "10": { + "title": "Test Country", + "country": "Test", + "warning": "Be careful.", + "lastChanged": "2026-03-01" + } + }}`) + items, err := ParseGermanAATravelWarnings(body) + if err != nil { + t.Fatal(err) + } + if len(items) != 1 { + t.Fatalf("expected 1 item, got %d", len(items)) + } + if items[0].Title != "Test Country" { + t.Errorf("unexpected title: %s", items[0].Title) + } +} + +func TestParseFCDOAtom(t *testing.T) { + body := []byte(` + + FCDO Travel Advice + + Afghanistan travel advice + + 2026-01-10T12:00:00Z + FCDO advises against all travel to Afghanistan. + + `) + items, err := ParseFCDOAtom(body) + if err != nil { + t.Fatal(err) + } + if len(items) != 1 { + t.Fatalf("expected 1 item, got %d", len(items)) + } + if items[0].Title != "Afghanistan travel advice" { + t.Errorf("unexpected title: %s", items[0].Title) + } + if items[0].Link != "https://www.gov.uk/foreign-travel-advice/afghanistan" { + t.Errorf("unexpected link: %s", items[0].Link) + } +} diff --git a/internal/collector/registry/registry.go b/internal/collector/registry/registry.go index 3d1cbcf..7acffd1 100644 --- a/internal/collector/registry/registry.go +++ b/internal/collector/registry/registry.go @@ -4,16 +4,32 @@ package registry import ( + "context" "encoding/json" "fmt" "os" + "path/filepath" "sort" "strings" "github.com/scalytics/euosint/internal/collector/model" + "github.com/scalytics/euosint/internal/sourcedb" ) func Load(path string) ([]model.RegistrySource, error) { + if isSQLitePath(path) { + db, err := sourcedb.Open(path) + if err != nil { + return nil, err + } + defer db.Close() + raw, err := db.LoadActiveSources(context.Background()) + if err != nil { + return nil, fmt.Errorf("load registry from source DB %s: %w", path, err) + } + return normalizeAll(raw), nil + } + data, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf("read registry %s: %w", path, err) @@ -24,24 +40,7 @@ func Load(path string) ([]model.RegistrySource, error) { return nil, fmt.Errorf("decode registry %s: %w", path, err) } - seen := make(map[string]struct{}, len(raw)) - out := make([]model.RegistrySource, 0, len(raw)) - for _, entry := range raw { - normalized, ok := normalize(entry) - if !ok { - continue - } - if _, exists := seen[normalized.Source.SourceID]; exists { - continue - } - seen[normalized.Source.SourceID] = struct{}{} - out = append(out, normalized) - } - - sort.Slice(out, func(i, j int) bool { - return out[i].Source.SourceID < out[j].Source.SourceID - }) - return out, nil + return normalizeAll(raw), nil } func normalize(entry model.RegistrySource) (model.RegistrySource, bool) { @@ -74,3 +73,32 @@ func fallback(value, fallback string) string { } return strings.TrimSpace(value) } + +func normalizeAll(raw []model.RegistrySource) []model.RegistrySource { + seen := make(map[string]struct{}, len(raw)) + out := make([]model.RegistrySource, 0, len(raw)) + for _, entry := range raw { + normalized, ok := normalize(entry) + if !ok { + continue + } + if _, exists := seen[normalized.Source.SourceID]; exists { + continue + } + seen[normalized.Source.SourceID] = struct{}{} + out = append(out, normalized) + } + sort.Slice(out, func(i, j int) bool { + return out[i].Source.SourceID < out[j].Source.SourceID + }) + return out +} + +func isSQLitePath(path string) bool { + switch strings.ToLower(filepath.Ext(strings.TrimSpace(path))) { + case ".db", ".sqlite", ".sqlite3": + return true + default: + return false + } +} diff --git a/internal/collector/registry/registry_test.go b/internal/collector/registry/registry_test.go index 1b4ce08..63a225f 100644 --- a/internal/collector/registry/registry_test.go +++ b/internal/collector/registry/registry_test.go @@ -7,6 +7,8 @@ import ( "os" "path/filepath" "testing" + + "github.com/scalytics/euosint/internal/sourcedb" ) func TestLoadRegistryDeduplicatesAndNormalizes(t *testing.T) { @@ -34,3 +36,34 @@ func TestLoadRegistryDeduplicatesAndNormalizes(t *testing.T) { t.Fatalf("expected normalized country code, got %q", sources[0].Source.CountryCode) } } + +func TestLoadRegistryFromSQLite(t *testing.T) { + dir := t.TempDir() + jsonPath := filepath.Join(dir, "registry.json") + dbPath := filepath.Join(dir, "sources.db") + content := `[ + {"type":"rss","feed_url":"https://one.example/feed","category":"cyber_advisory","source":{"source_id":"one-feed","authority_name":"Agency One","country":"France","country_code":"fr","region":"Europe","authority_type":"cert","base_url":"https://one.example"}} + ]` + if err := os.WriteFile(jsonPath, []byte(content), 0o644); err != nil { + t.Fatal(err) + } + db, err := sourcedb.Open(dbPath) + if err != nil { + t.Fatal(err) + } + defer db.Close() + if err := db.ImportRegistry(t.Context(), jsonPath); err != nil { + t.Fatal(err) + } + + sources, err := Load(dbPath) + if err != nil { + t.Fatal(err) + } + if len(sources) != 1 { + t.Fatalf("expected 1 source from sqlite registry, got %d", len(sources)) + } + if sources[0].Source.CountryCode != "FR" { + t.Fatalf("expected normalized country code, got %q", sources[0].Source.CountryCode) + } +} diff --git a/internal/collector/run/run.go b/internal/collector/run/run.go index 3f18e25..394cfe0 100644 --- a/internal/collector/run/run.go +++ b/internal/collector/run/run.go @@ -9,10 +9,13 @@ import ( "fmt" "io" "net/url" + "path/filepath" "strings" "time" "github.com/scalytics/euosint/internal/collector/config" + "github.com/scalytics/euosint/internal/collector/dictionary" + "github.com/scalytics/euosint/internal/collector/discover" "github.com/scalytics/euosint/internal/collector/fetch" "github.com/scalytics/euosint/internal/collector/model" "github.com/scalytics/euosint/internal/collector/normalize" @@ -21,12 +24,15 @@ import ( "github.com/scalytics/euosint/internal/collector/registry" "github.com/scalytics/euosint/internal/collector/state" "github.com/scalytics/euosint/internal/collector/translate" + "github.com/scalytics/euosint/internal/collector/vet" + "github.com/scalytics/euosint/internal/sourcedb" ) type Runner struct { - stdout io.Writer - stderr io.Writer - clientFactory func(config.Config) *fetch.Client + stdout io.Writer + stderr io.Writer + clientFactory func(config.Config) *fetch.Client + browserFactory func(config.Config) (*fetch.BrowserClient, error) } func New(stdout io.Writer, stderr io.Writer) Runner { @@ -34,10 +40,16 @@ func New(stdout io.Writer, stderr io.Writer) Runner { stdout: stdout, stderr: stderr, clientFactory: fetch.New, + browserFactory: func(cfg config.Config) (*fetch.BrowserClient, error) { + return fetch.NewBrowser(cfg.BrowserTimeoutMS) + }, } } func (r Runner) Run(ctx context.Context, cfg config.Config) error { + if cfg.Watch && cfg.DiscoverBackground { + go r.runDiscoveryLoop(ctx, cfg) + } if cfg.Watch { return r.watch(ctx, cfg) } @@ -66,14 +78,31 @@ func (r Runner) runOnce(ctx context.Context, cfg config.Config) error { return err } client := r.clientFactory(cfg) + + var browser *fetch.BrowserClient + if cfg.BrowserEnabled && r.browserFactory != nil { + b, err := r.browserFactory(cfg) + if err != nil { + fmt.Fprintf(r.stderr, "WARN browser init failed (falling back to stealth): %v\n", err) + } else { + browser = b + defer browser.Close() + } + } + now := time.Now().UTC() nctx := normalize.Context{Config: cfg, Now: now} + categoryDictionary, err := dictionary.Load(cfg.CategoryDictionaryPath) + if err != nil { + fmt.Fprintf(r.stderr, "WARN category dictionary load failed (falling back to legacy filters): %v\n", err) + } alerts := []model.Alert{normalize.StaticInterpolEntry(now)} sourceHealth := make([]model.SourceHealthEntry, 0, len(sources)) for _, source := range sources { startedAt := time.Now().UTC() - batch, err := r.fetchSource(ctx, client, nctx, source) + fetcher := fetch.FetcherFor(source.FetchMode, client, browser) + batch, err := r.fetchSource(ctx, fetcher, nctx, source, categoryDictionary) entry := model.SourceHealthEntry{ SourceID: source.Source.SourceID, AuthorityName: source.Source.AuthorityName, @@ -85,6 +114,7 @@ func (r Runner) runOnce(ctx context.Context, cfg config.Config) error { if err != nil { entry.Status = "error" entry.Error = err.Error() + entry.ErrorClass, entry.NeedsReplacement, entry.DiscoveryAction = classifySourceError(err) sourceHealth = append(sourceHealth, entry) fmt.Fprintf(r.stderr, "WARN %s: %v\n", source.Source.AuthorityName, err) continue @@ -102,41 +132,54 @@ func (r Runner) runOnce(ctx context.Context, cfg config.Config) error { return err } - previous := state.Read(cfg.StateOutputPath) - if len(previous) == 0 { - previous = state.Read(cfg.OutputPath) + previous, err := loadPreviousAlerts(ctx, cfg) + if err != nil { + return err } currentActive, currentFiltered, fullState := state.Reconcile(cfg, active, filtered, previous, now) - if err := output.Write(cfg, currentActive, currentFiltered, fullState, sourceHealth, duplicateAudit); err != nil { + replacementQueue := buildReplacementQueue(sourceHealth, sources) + if err := deactivateReplacementSources(ctx, cfg.RegistryPath, replacementQueue); err != nil { + return err + } + if err := saveAlertState(ctx, cfg, fullState); err != nil { + return err + } + if err := output.Write(cfg, currentActive, currentFiltered, fullState, sourceHealth, duplicateAudit, replacementQueue); err != nil { return err } _, err = fmt.Fprintf(r.stdout, "Wrote %d active alerts -> %s (%d filtered in %s)\n", len(currentActive), cfg.OutputPath, len(currentFiltered), cfg.FilteredOutputPath) return err } -func (r Runner) fetchSource(ctx context.Context, client *fetch.Client, nctx normalize.Context, source model.RegistrySource) ([]model.Alert, error) { +func (r Runner) fetchSource(ctx context.Context, fetcher fetch.Fetcher, nctx normalize.Context, source model.RegistrySource, categoryDictionary *dictionary.Store) ([]model.Alert, error) { switch source.Type { case "rss": - return r.fetchRSS(ctx, client, nctx, source) + return r.fetchRSS(ctx, fetcher, nctx, source) case "html-list": - return r.fetchHTML(ctx, client, nctx, source) + return r.fetchHTML(ctx, fetcher, nctx, source, categoryDictionary) case "kev-json": - return r.fetchKEV(ctx, client, nctx, source) + return r.fetchKEV(ctx, fetcher, nctx, source) case "interpol-red-json", "interpol-yellow-json": - return r.fetchInterpol(ctx, client, nctx, source) + return r.fetchInterpol(ctx, fetcher, nctx, source) + case "travelwarning-json": + return r.fetchTravelWarningJSON(ctx, fetcher, nctx, source) + case "travelwarning-atom": + return r.fetchTravelWarningAtom(ctx, fetcher, nctx, source) default: return nil, fmt.Errorf("unsupported source type %s", source.Type) } } -func (r Runner) fetchRSS(ctx context.Context, client *fetch.Client, nctx normalize.Context, source model.RegistrySource) ([]model.Alert, error) { - body, err := fetchWithFallback(ctx, client, source, "application/rss+xml, application/atom+xml, application/xml, text/xml;q=0.9, */*;q=0.8") +func (r Runner) fetchRSS(ctx context.Context, fetcher fetch.Fetcher, nctx normalize.Context, source model.RegistrySource) ([]model.Alert, error) { + body, err := fetchWithFallback(ctx, fetcher, source, "application/rss+xml, application/atom+xml, application/xml, text/xml;q=0.9, */*;q=0.8") if err != nil { return nil, err } items := parse.ParseFeed(string(body)) if nctx.Config.TranslateEnabled { - if translated, err := translate.Batch(ctx, client, items); err == nil { + // translate.Batch requires the stealth HTTP client (not a browser). + translateClient := r.clientFactory(nctx.Config) + if translated, err := translate.Batch(ctx, translateClient, items); err == nil { items = translated } else { fmt.Fprintf(r.stderr, "WARN %s: translate batch failed: %v\n", source.Source.AuthorityName, err) @@ -144,6 +187,36 @@ func (r Runner) fetchRSS(ctx context.Context, client *fetch.Client, nctx normali } limit := perSourceLimit(nctx.Config, source) out := make([]model.Alert, 0, limit) + if nctx.Config.AlertLLMEnabled { + alertLLM := vet.NewClient(config.Config{ + HTTPTimeoutMS: nctx.Config.HTTPTimeoutMS, + VettingBaseURL: nctx.Config.VettingBaseURL, + VettingAPIKey: nctx.Config.VettingAPIKey, + VettingProvider: nctx.Config.VettingProvider, + VettingModel: nctx.Config.AlertLLMModel, + VettingTemperature: 0, + }) + classified, err := translate.BatchLLM(ctx, nctx.Config, alertLLM, source.Category, items) + if err != nil { + fmt.Fprintf(r.stderr, "WARN %s: alert llm failed: %v\n", source.Source.AuthorityName, err) + } else { + for _, classifiedItem := range classified { + if len(out) == limit { + break + } + if strings.TrimSpace(classifiedItem.Item.Title) == "" || strings.TrimSpace(classifiedItem.Item.Link) == "" { + continue + } + meta := source + meta.Category = firstNonEmpty(classifiedItem.Category, source.Category) + alert := normalize.RSSItem(nctx, meta, classifiedItem.Item) + if alert != nil { + out = append(out, *alert) + } + } + return out, nil + } + } for _, item := range items { if len(out) == limit { break @@ -159,18 +232,43 @@ func (r Runner) fetchRSS(ctx context.Context, client *fetch.Client, nctx normali return out, nil } -func (r Runner) fetchHTML(ctx context.Context, client *fetch.Client, nctx normalize.Context, source model.RegistrySource) ([]model.Alert, error) { - body, finalURL, err := fetchWithFallbackURL(ctx, client, source, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") +func (r Runner) fetchHTML(ctx context.Context, fetcher fetch.Fetcher, nctx normalize.Context, source model.RegistrySource, categoryDictionary *dictionary.Store) ([]model.Alert, error) { + body, finalURL, err := fetchWithFallbackURL(ctx, fetcher, source, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") if err != nil { return nil, err } items := parse.ParseHTMLAnchors(string(body), finalURL) items = filterKeywords(items, source.IncludeKeywords, source.ExcludeKeywords) + items = filterCategoryItems(items, source, categoryDictionary) limit := perSourceLimit(nctx.Config, source) if len(items) > limit { items = items[:limit] } out := make([]model.Alert, 0, len(items)) + if nctx.Config.AlertLLMEnabled { + alertLLM := vet.NewClient(config.Config{ + HTTPTimeoutMS: nctx.Config.HTTPTimeoutMS, + VettingBaseURL: nctx.Config.VettingBaseURL, + VettingAPIKey: nctx.Config.VettingAPIKey, + VettingProvider: nctx.Config.VettingProvider, + VettingModel: nctx.Config.AlertLLMModel, + VettingTemperature: 0, + }) + classified, err := translate.BatchLLM(ctx, nctx.Config, alertLLM, source.Category, items) + if err != nil { + fmt.Fprintf(r.stderr, "WARN %s: alert llm failed: %v\n", source.Source.AuthorityName, err) + } else { + for _, classifiedItem := range classified { + meta := source + meta.Category = firstNonEmpty(classifiedItem.Category, source.Category) + alert := normalize.HTMLItem(nctx, meta, classifiedItem.Item) + if alert != nil { + out = append(out, *alert) + } + } + return out, nil + } + } for _, item := range items { alert := normalize.HTMLItem(nctx, source, item) if alert != nil { @@ -180,8 +278,8 @@ func (r Runner) fetchHTML(ctx context.Context, client *fetch.Client, nctx normal return out, nil } -func (r Runner) fetchKEV(ctx context.Context, client *fetch.Client, nctx normalize.Context, source model.RegistrySource) ([]model.Alert, error) { - body, err := client.Text(ctx, source.FeedURL, source.FollowRedirects, "application/json") +func (r Runner) fetchKEV(ctx context.Context, fetcher fetch.Fetcher, nctx normalize.Context, source model.RegistrySource) ([]model.Alert, error) { + body, err := fetcher.Text(ctx, source.FeedURL, source.FollowRedirects, "application/json") if err != nil { return nil, err } @@ -214,8 +312,8 @@ func (r Runner) fetchKEV(ctx context.Context, client *fetch.Client, nctx normali return out, nil } -func (r Runner) fetchInterpol(ctx context.Context, client *fetch.Client, nctx normalize.Context, source model.RegistrySource) ([]model.Alert, error) { - body, err := client.Text(ctx, source.FeedURL, source.FollowRedirects, "application/json") +func (r Runner) fetchInterpol(ctx context.Context, fetcher fetch.Fetcher, nctx normalize.Context, source model.RegistrySource) ([]model.Alert, error) { + body, err := fetcher.Text(ctx, source.FeedURL, source.FollowRedirects, "application/json") if err != nil { return nil, err } @@ -277,12 +375,64 @@ func (r Runner) fetchInterpol(ctx context.Context, client *fetch.Client, nctx no return out, nil } -func fetchWithFallback(ctx context.Context, client *fetch.Client, source model.RegistrySource, accept string) ([]byte, error) { - body, _, err := fetchWithFallbackURL(ctx, client, source, accept) +func (r Runner) fetchTravelWarningJSON(ctx context.Context, fetcher fetch.Fetcher, nctx normalize.Context, source model.RegistrySource) ([]model.Alert, error) { + body, err := fetcher.Text(ctx, source.FeedURL, source.FollowRedirects, "application/json") + if err != nil { + return nil, err + } + items, err := parse.ParseGermanAATravelWarnings(body) + if err != nil { + return nil, err + } + limit := perSourceLimit(nctx.Config, source) + out := make([]model.Alert, 0, limit) + for _, item := range items { + if len(out) == limit { + break + } + if strings.TrimSpace(item.Title) == "" { + continue + } + alert := normalize.TravelWarningAlert(nctx, source, item) + if alert != nil { + out = append(out, *alert) + } + } + return out, nil +} + +func (r Runner) fetchTravelWarningAtom(ctx context.Context, fetcher fetch.Fetcher, nctx normalize.Context, source model.RegistrySource) ([]model.Alert, error) { + body, err := fetchWithFallback(ctx, fetcher, source, "application/atom+xml, application/xml, text/xml;q=0.9, */*;q=0.8") + if err != nil { + return nil, err + } + items, err := parse.ParseFCDOAtom(body) + if err != nil { + return nil, err + } + limit := perSourceLimit(nctx.Config, source) + out := make([]model.Alert, 0, limit) + for _, item := range items { + if len(out) == limit { + break + } + if strings.TrimSpace(item.Title) == "" || strings.TrimSpace(item.Link) == "" { + continue + } + alert := normalize.TravelWarningAlert(nctx, source, item) + if alert != nil { + out = append(out, *alert) + } + } + return out, nil +} + +func fetchWithFallback(ctx context.Context, fetcher fetch.Fetcher, source model.RegistrySource, accept string) ([]byte, error) { + body, _, err := fetchWithFallbackURL(ctx, fetcher, source, accept) return body, err } -func fetchWithFallbackURL(ctx context.Context, client *fetch.Client, source model.RegistrySource, accept string) ([]byte, string, error) { +func fetchWithFallbackURL(ctx context.Context, fetcher fetch.Fetcher, source model.RegistrySource, accept string) ([]byte, string, error) { candidates := []string{} if strings.TrimSpace(source.FeedURL) != "" { candidates = append(candidates, source.FeedURL) @@ -290,7 +440,7 @@ func fetchWithFallbackURL(ctx context.Context, client *fetch.Client, source mode candidates = append(candidates, source.FeedURLs...) var lastErr error for _, candidate := range candidates { - body, err := client.Text(ctx, candidate, source.FollowRedirects, accept) + body, err := fetcher.Text(ctx, candidate, source.FollowRedirects, accept) if err == nil { return body, candidate, nil } @@ -339,6 +489,19 @@ func containsKeyword(hay string, needles []string) bool { return false } +func filterCategoryItems(items []parse.FeedItem, source model.RegistrySource, categoryDictionary *dictionary.Store) []parse.FeedItem { + if categoryDictionary == nil { + return items + } + out := make([]parse.FeedItem, 0, len(items)) + for _, item := range items { + if categoryDictionary.Match(source.Category, source, item.Title, item.Link) { + out = append(out, item) + } + } + return out +} + func populateSourceHealth(entries []model.SourceHealthEntry, active []model.Alert, filtered []model.Alert) { activeBySource := map[string]int{} filteredBySource := map[string]int{} @@ -392,3 +555,156 @@ func firstNonEmpty(values ...string) string { } return "" } + +func (r Runner) runDiscoveryLoop(ctx context.Context, cfg config.Config) { + runOnce := func() { + if err := discover.Run(ctx, cfg, r.stdout, r.stderr); err != nil && ctx.Err() == nil { + fmt.Fprintf(r.stderr, "WARN background discovery failed: %v\n", err) + } + } + + runOnce() + + interval := time.Duration(cfg.DiscoverIntervalMS) * time.Millisecond + if interval <= 0 { + interval = 15 * time.Minute + } + ticker := time.NewTicker(interval) + defer ticker.Stop() + + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + runOnce() + } + } +} + +func classifySourceError(err error) (string, bool, string) { + if err == nil { + return "", false, "" + } + msg := strings.ToLower(err.Error()) + switch { + case strings.Contains(msg, "status 404"), strings.Contains(msg, "status 410"): + return "not_found", true, "dead_letter" + case strings.Contains(msg, "status 301"), strings.Contains(msg, "status 302"), strings.Contains(msg, "status 307"), strings.Contains(msg, "status 308"): + return "redirect", true, "dead_letter" + case strings.Contains(msg, "status 403"): + return "blocked", true, "dead_letter" + case strings.Contains(msg, "response too large"): + return "oversized", true, "dead_letter" + case strings.Contains(msg, "certificate signed by unknown authority"): + return "tls_invalid", true, "dead_letter" + case strings.Contains(msg, "no such host"): + return "dns_error", true, "dead_letter" + case strings.Contains(msg, "client.timeout exceeded"), strings.Contains(msg, "request canceled"), strings.Contains(msg, "timeout"): + return "timeout", false, "retry" + case strings.Contains(msg, ": eof"), strings.HasSuffix(msg, " eof"): + return "eof", false, "retry" + default: + return "transient", false, "retry" + } +} + +func buildReplacementQueue(entries []model.SourceHealthEntry, sources []model.RegistrySource) []model.SourceReplacementCandidate { + byID := make(map[string]model.RegistrySource, len(sources)) + for _, source := range sources { + byID[source.Source.SourceID] = source + } + + queue := make([]model.SourceReplacementCandidate, 0) + for _, entry := range entries { + if !entry.NeedsReplacement { + continue + } + source, ok := byID[entry.SourceID] + if !ok { + continue + } + queue = append(queue, model.SourceReplacementCandidate{ + SourceID: entry.SourceID, + AuthorityName: entry.AuthorityName, + Type: entry.Type, + FeedURL: entry.FeedURL, + BaseURL: source.Source.BaseURL, + Country: source.Source.Country, + CountryCode: source.Source.CountryCode, + Region: source.Source.Region, + AuthorityType: source.Source.AuthorityType, + Category: source.Category, + Error: entry.Error, + ErrorClass: entry.ErrorClass, + DiscoveryAction: entry.DiscoveryAction, + LastAttemptAt: entry.FinishedAt, + }) + } + return queue +} + +func deactivateReplacementSources(ctx context.Context, registryPath string, queue []model.SourceReplacementCandidate) error { + if !isSQLiteRegistryPath(registryPath) || len(queue) == 0 { + return nil + } + db, err := sourcedb.Open(registryPath) + if err != nil { + return err + } + defer db.Close() + + reasons := make(map[string]string, len(queue)) + for _, candidate := range queue { + reasons[candidate.SourceID] = candidate.Error + } + return db.DeactivateSources(ctx, reasons) +} + +func loadPreviousAlerts(ctx context.Context, cfg config.Config) ([]model.Alert, error) { + if !isSQLiteRegistryPath(cfg.RegistryPath) { + previous := state.Read(cfg.StateOutputPath) + if len(previous) == 0 { + previous = state.Read(cfg.OutputPath) + } + return previous, nil + } + + db, err := sourcedb.Open(cfg.RegistryPath) + if err != nil { + return nil, fmt.Errorf("open source DB for alert state: %w", err) + } + defer db.Close() + + alerts, err := db.LoadAlerts(ctx) + if err != nil { + return nil, fmt.Errorf("load alert state from source DB: %w", err) + } + return alerts, nil +} + +func saveAlertState(ctx context.Context, cfg config.Config, alerts []model.Alert) error { + if !isSQLiteRegistryPath(cfg.RegistryPath) { + return nil + } + + db, err := sourcedb.Open(cfg.RegistryPath) + if err != nil { + return fmt.Errorf("open source DB for alert save: %w", err) + } + defer db.Close() + + if err := db.SaveAlerts(ctx, alerts); err != nil { + return fmt.Errorf("save alert state to source DB: %w", err) + } + return nil +} + +func isSQLiteRegistryPath(path string) bool { + switch strings.ToLower(filepath.Ext(strings.TrimSpace(path))) { + case ".db", ".sqlite", ".sqlite3": + return true + default: + return false + } +} diff --git a/internal/collector/run/run_test.go b/internal/collector/run/run_test.go index 6fb3af6..16ab31a 100644 --- a/internal/collector/run/run_test.go +++ b/internal/collector/run/run_test.go @@ -12,10 +12,14 @@ import ( "path/filepath" "strings" "testing" + "time" "github.com/scalytics/euosint/internal/collector/config" + "github.com/scalytics/euosint/internal/collector/dictionary" "github.com/scalytics/euosint/internal/collector/fetch" "github.com/scalytics/euosint/internal/collector/model" + "github.com/scalytics/euosint/internal/collector/parse" + "github.com/scalytics/euosint/internal/sourcedb" ) func TestRunnerRunOnceWritesOutputs(t *testing.T) { @@ -25,7 +29,9 @@ func TestRunnerRunOnceWritesOutputs(t *testing.T) { {"type":"rss","feed_url":"https://collector.test/rss","category":"cyber_advisory","region_tag":"INT","lat":48.8,"lng":2.3,"source":{"source_id":"rss-source","authority_name":"RSS Source","country":"France","country_code":"FR","region":"Europe","authority_type":"cert","base_url":"https://collector.test"}}, {"type":"html-list","feed_url":"https://collector.test/html","category":"wanted_suspect","region_tag":"FR","lat":48.8,"lng":2.3,"include_keywords":["wanted"],"source":{"source_id":"html-source","authority_name":"HTML Source","country":"France","country_code":"FR","region":"Europe","authority_type":"police","base_url":"https://collector.test"}}, {"type":"kev-json","feed_url":"https://collector.test/kev","category":"cyber_advisory","region_tag":"US","lat":38.8,"lng":-77.0,"source":{"source_id":"kev-source","authority_name":"KEV Source","country":"United States","country_code":"US","region":"North America","authority_type":"cert","base_url":"https://www.cisa.gov"}}, - {"type":"interpol-red-json","feed_url":"https://collector.test/interpol","category":"wanted_suspect","region_tag":"INT","lat":45.7,"lng":4.8,"source":{"source_id":"interpol-red","authority_name":"Interpol Red","country":"France","country_code":"FR","region":"International","authority_type":"police","base_url":"https://www.interpol.int"}} + {"type":"interpol-red-json","feed_url":"https://collector.test/interpol","category":"wanted_suspect","region_tag":"INT","lat":45.7,"lng":4.8,"source":{"source_id":"interpol-red","authority_name":"Interpol Red","country":"France","country_code":"FR","region":"International","authority_type":"police","base_url":"https://www.interpol.int"}}, + {"type":"travelwarning-json","feed_url":"https://collector.test/travel-json","category":"travel_warning","region_tag":"DE","lat":52.5,"lng":13.4,"source":{"source_id":"de-aa-travel","authority_name":"German AA","country":"Germany","country_code":"DE","region":"Europe","authority_type":"national_security","base_url":"https://www.auswaertiges-amt.de"}}, + {"type":"travelwarning-atom","feed_url":"https://collector.test/travel-atom","category":"travel_warning","region_tag":"GB","lat":51.5,"lng":-0.1,"source":{"source_id":"uk-fcdo-travel","authority_name":"UK FCDO","country":"United Kingdom","country_code":"GB","region":"Europe","authority_type":"national_security","base_url":"https://www.gov.uk"}} ]`) if err := os.WriteFile(registryPath, registry, 0o644); err != nil { t.Fatal(err) @@ -37,6 +43,7 @@ func TestRunnerRunOnceWritesOutputs(t *testing.T) { cfg.FilteredOutputPath = filepath.Join(dir, "filtered.json") cfg.StateOutputPath = filepath.Join(dir, "state.json") cfg.SourceHealthOutputPath = filepath.Join(dir, "health.json") + cfg.ReplacementQueuePath = filepath.Join(dir, "replacement.json") cfg.MaxAgeDays = 10000 runner := New(io.Discard, io.Discard) @@ -53,6 +60,10 @@ func TestRunnerRunOnceWritesOutputs(t *testing.T) { body = `{"vulnerabilities":[{"cveID":"CVE-2026-9999","vulnerabilityName":"Test vuln","shortDescription":"Known exploited issue","dateAdded":"2026-01-01","knownRansomwareCampaign":true}]}` case "/interpol": body = `{"_embedded":{"notices":[{"forename":"Jane","name":"Doe","issuing_entity":"Interpol","place_of_birth":"Paris","nationalities":["FR"],"_links":{"self":{"href":"https://ws-public.interpol.int/notices/v1/red/123"}}}]}}` + case "/travel-json": + body = `{"1":{"title":"Afghanistan - Do not travel","country":"Afghanistan","warning":"Do not travel.","severity":"Reisewarnung","lastChanged":"2026-01-15","url":"https://example.com/af"}}` + case "/travel-atom": + body = `France travel advice2026-02-01T00:00:00ZExercise normal caution.` default: return &http.Response{StatusCode: 404, Body: io.NopCloser(strings.NewReader("not found")), Header: make(http.Header)}, nil } @@ -84,9 +95,205 @@ func TestRunnerRunOnceWritesOutputs(t *testing.T) { if err := json.Unmarshal(rawHealth, &health); err != nil { t.Fatal(err) } - if health.TotalSources != 4 { - t.Fatalf("expected 4 sources in health document, got %d", health.TotalSources) + if health.TotalSources != 6 { + t.Fatalf("expected 6 sources in health document, got %d", health.TotalSources) } + if len(health.ReplacementQueue) != 0 { + t.Fatalf("expected no replacement queue entries, got %d", len(health.ReplacementQueue)) + } + if _, err := os.Stat(cfg.ReplacementQueuePath); err != nil { + t.Fatalf("expected replacement queue output, got %v", err) + } +} + +func TestBuildReplacementQueueFromPermanentFailures(t *testing.T) { + sources := []model.RegistrySource{ + { + Type: "rss", + FeedURL: "https://collector.test/dead-feed", + Category: "cyber_advisory", + Source: model.SourceMetadata{ + SourceID: "dead-source", + AuthorityName: "Dead Source", + Country: "France", + CountryCode: "FR", + Region: "Europe", + AuthorityType: "cert", + BaseURL: "https://collector.test", + }, + }, + } + entries := []model.SourceHealthEntry{ + { + SourceID: "dead-source", + AuthorityName: "Dead Source", + Type: "rss", + Status: "error", + FeedURL: "https://collector.test/dead-feed", + Error: "fetch https://collector.test/dead-feed: status 404", + ErrorClass: "not_found", + NeedsReplacement: true, + DiscoveryAction: "find_replacement", + FinishedAt: "2026-03-16T12:00:00Z", + }, + } + + queue := buildReplacementQueue(entries, sources) + if len(queue) != 1 { + t.Fatalf("expected one queued replacement candidate, got %d", len(queue)) + } + if queue[0].BaseURL != "https://collector.test" { + t.Fatalf("expected base URL to be carried into replacement queue, got %q", queue[0].BaseURL) + } +} + +func TestFilterCategoryItemsDropsUnrelatedMissingPersonHTML(t *testing.T) { + dict, err := dictionary.Load(filepath.Join("..", "..", "..", "registry", "category_dictionary.json")) + if err != nil { + t.Fatal(err) + } + items := []parse.FeedItem{ + {Title: "Calendario de actividades", Link: "https://example.test/calendario"}, + {Title: "Persona desaparecida en San Jose", Link: "https://example.test/desaparecidos/1"}, + } + filtered := filterCategoryItems(items, model.RegistrySource{ + Category: "missing_person", + Source: model.SourceMetadata{CountryCode: "CR"}, + }, dict) + if len(filtered) != 1 { + t.Fatalf("expected only one missing-person item after filtering, got %d", len(filtered)) + } + if filtered[0].Link != "https://example.test/desaparecidos/1" { + t.Fatalf("unexpected retained item: %#v", filtered[0]) + } +} + +func TestFilterCategoryItemsDropsUnrelatedWantedHTML(t *testing.T) { + dict, err := dictionary.Load(filepath.Join("..", "..", "..", "registry", "category_dictionary.json")) + if err != nil { + t.Fatal(err) + } + items := []parse.FeedItem{ + {Title: "Institutional history", Link: "https://example.test/history"}, + {Title: "Wanted suspect public appeal", Link: "https://example.test/wanted/1"}, + } + filtered := filterCategoryItems(items, model.RegistrySource{ + Category: "wanted_suspect", + Source: model.SourceMetadata{CountryCode: "US"}, + }, dict) + if len(filtered) != 1 { + t.Fatalf("expected only one wanted item after filtering, got %d", len(filtered)) + } + if filtered[0].Link != "https://example.test/wanted/1" { + t.Fatalf("unexpected retained item: %#v", filtered[0]) + } +} + +func TestFilterCategoryItemsMatchesCatalanMissingPersonPage(t *testing.T) { + dict, err := dictionary.Load(filepath.Join("..", "..", "..", "registry", "category_dictionary.json")) + if err != nil { + t.Fatal(err) + } + items := []parse.FeedItem{ + {Title: "Persona desapareguda", Link: "https://example.test/_ca/persona-desapareguda"}, + } + filtered := filterCategoryItems(items, model.RegistrySource{ + Category: "missing_person", + FeedURL: "https://www.policia.es/_ca/comunicacion_salaprensa.php?idiomaActual=ca", + Source: model.SourceMetadata{CountryCode: "ES"}, + }, dict) + if len(filtered) != 1 { + t.Fatalf("expected Catalan missing-person page to be retained, got %d", len(filtered)) + } +} + +func TestRunnerRunOnceUsesSQLiteAlertStateWithoutDuplicatingAlerts(t *testing.T) { + dir := t.TempDir() + registryPath := filepath.Join(dir, "sources.db") + seedPath := filepath.Join(dir, "registry.json") + registry := []byte(`[ + {"type":"rss","feed_url":"https://collector.test/rss","category":"cyber_advisory","region_tag":"INT","lat":48.8,"lng":2.3,"source":{"source_id":"rss-source","authority_name":"RSS Source","country":"France","country_code":"FR","region":"Europe","authority_type":"cert","base_url":"https://collector.test","language_code":"en"}} + ]`) + if err := os.WriteFile(seedPath, registry, 0o644); err != nil { + t.Fatal(err) + } + + db, err := sourcedb.Open(registryPath) + if err != nil { + t.Fatal(err) + } + if err := db.ImportRegistry(context.Background(), seedPath); err != nil { + db.Close() + t.Fatal(err) + } + db.Close() + + cfg := config.Default() + cfg.RegistryPath = registryPath + cfg.OutputPath = filepath.Join(dir, "alerts.json") + cfg.FilteredOutputPath = filepath.Join(dir, "filtered.json") + cfg.StateOutputPath = filepath.Join(dir, "state.json") + cfg.SourceHealthOutputPath = filepath.Join(dir, "health.json") + cfg.ReplacementQueuePath = filepath.Join(dir, "replacement.json") + cfg.MaxAgeDays = 10000 + + runner := New(io.Discard, io.Discard) + runner.clientFactory = func(cfg config.Config) *fetch.Client { + return fetch.NewWithHTTPClient(cfg, &http.Client{ + Transport: roundTripFunc(func(req *http.Request) (*http.Response, error) { + if req.URL.Path != "/rss" { + return &http.Response{StatusCode: 404, Body: io.NopCloser(strings.NewReader("not found")), Header: make(http.Header)}, nil + } + body := `alert-1Critical cyber advisoryhttps://collector.test/rss-itemMon, 02 Jan 2026 15:04:05 MSTCVE-2026-1234 patch advisory` + return &http.Response{StatusCode: 200, Body: io.NopCloser(strings.NewReader(body)), Header: make(http.Header)}, nil + }), + }) + } + + if err := runner.Run(context.Background(), cfg); err != nil { + t.Fatal(err) + } + persistedAfterFirstRun, err := loadPersistedAlerts(registryPath) + if err != nil { + t.Fatal(err) + } + if len(persistedAfterFirstRun) != 2 { + t.Fatalf("expected 2 persisted alerts after first run, got %d", len(persistedAfterFirstRun)) + } + + firstSeenByID := map[string]string{} + for _, alert := range persistedAfterFirstRun { + firstSeenByID[alert.AlertID] = alert.FirstSeen + } + + time.Sleep(1100 * time.Millisecond) + + if err := runner.Run(context.Background(), cfg); err != nil { + t.Fatal(err) + } + persistedAfterSecondRun, err := loadPersistedAlerts(registryPath) + if err != nil { + t.Fatal(err) + } + if len(persistedAfterSecondRun) != 2 { + t.Fatalf("expected 2 persisted alerts after second run, got %d", len(persistedAfterSecondRun)) + } + for _, alert := range persistedAfterSecondRun { + if want := firstSeenByID[alert.AlertID]; want == "" { + t.Fatalf("unexpected alert persisted after second run: %q", alert.AlertID) + } else if alert.FirstSeen != want { + t.Fatalf("expected first_seen for %s to remain %q, got %q", alert.AlertID, want, alert.FirstSeen) + } + } +} + +func loadPersistedAlerts(dbPath string) ([]model.Alert, error) { + db, err := sourcedb.Open(dbPath) + if err != nil { + return nil, err + } + defer db.Close() + return db.LoadAlerts(context.Background()) } type roundTripFunc func(*http.Request) (*http.Response, error) diff --git a/internal/collector/translate/llm.go b/internal/collector/translate/llm.go new file mode 100644 index 0000000..e89bd99 --- /dev/null +++ b/internal/collector/translate/llm.go @@ -0,0 +1,108 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package translate + +import ( + "context" + "encoding/json" + "fmt" + "regexp" + "strings" + + "github.com/scalytics/euosint/internal/collector/config" + "github.com/scalytics/euosint/internal/collector/parse" + "github.com/scalytics/euosint/internal/collector/vet" +) + +type ClassifiedItem struct { + Item parse.FeedItem + Category string +} + +type AlertLLMResponse struct { + Yes bool `json:"yes"` + Translation string `json:"translation"` + CategoryID string `json:"category_id"` +} + +type Completer interface { + Complete(ctx context.Context, messages []vet.Message) (string, error) +} + +func BatchLLM(ctx context.Context, cfg config.Config, client Completer, defaultCategory string, items []parse.FeedItem) ([]ClassifiedItem, error) { + out := make([]ClassifiedItem, 0, len(items)) + for _, item := range items { + result, err := classifyItem(ctx, client, cfg.AlertLLMModel, defaultCategory, item) + if err != nil { + return nil, err + } + if !result.Yes { + continue + } + next := item + if strings.TrimSpace(result.Translation) != "" { + next.Title = strings.TrimSpace(result.Translation) + } + out = append(out, ClassifiedItem{ + Item: next, + Category: firstNonEmpty(result.CategoryID, defaultCategory), + }) + } + return out, nil +} + +func classifyItem(ctx context.Context, client Completer, model string, defaultCategory string, item parse.FeedItem) (AlertLLMResponse, error) { + payload, err := json.MarshalIndent(map[string]any{ + "default_category": defaultCategory, + "title": strings.TrimSpace(item.Title), + "summary": strings.TrimSpace(item.Summary), + "link": strings.TrimSpace(item.Link), + "tags": item.Tags, + }, "", " ") + if err != nil { + return AlertLLMResponse{}, fmt.Errorf("marshal alert llm input: %w", err) + } + + content, err := client.Complete(ctx, []vet.Message{ + { + Role: "system", + Content: "You classify a public source alert item. Return strict JSON only with keys yes, translation, category_id. yes must be true only for intelligence-relevant alerts, not generic information/noise. translation must be a short English title. category_id must be one of the known category ids or the supplied default_category.", + }, + { + Role: "user", + Content: "Model: " + model + "\nEvaluate this item and return JSON only.\n\n" + string(payload), + }, + }) + if err != nil { + return AlertLLMResponse{}, err + } + + return decodeAlertLLMResponse(content) +} + +var alertJSONBlockRe = regexp.MustCompile(`(?s)\{.*\}`) + +func decodeAlertLLMResponse(content string) (AlertLLMResponse, error) { + content = strings.TrimSpace(content) + if match := alertJSONBlockRe.FindString(content); match != "" { + content = match + } + var out AlertLLMResponse + if err := json.Unmarshal([]byte(content), &out); err != nil { + return AlertLLMResponse{}, fmt.Errorf("decode alert llm response: %w", err) + } + out.Translation = strings.TrimSpace(out.Translation) + out.CategoryID = strings.TrimSpace(out.CategoryID) + return out, nil +} + +func firstNonEmpty(values ...string) string { + for _, value := range values { + value = strings.TrimSpace(value) + if value != "" { + return value + } + } + return "" +} diff --git a/internal/collector/translate/llm_test.go b/internal/collector/translate/llm_test.go new file mode 100644 index 0000000..d8e5465 --- /dev/null +++ b/internal/collector/translate/llm_test.go @@ -0,0 +1,60 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package translate + +import ( + "context" + "testing" + + "github.com/scalytics/euosint/internal/collector/config" + "github.com/scalytics/euosint/internal/collector/parse" + "github.com/scalytics/euosint/internal/collector/vet" +) + +type fakeCompleter struct { + content string + err error +} + +func (f fakeCompleter) Complete(ctx context.Context, messages []vet.Message) (string, error) { + return f.content, f.err +} + +func TestDecodeAlertLLMResponse(t *testing.T) { + got, err := decodeAlertLLMResponse("```json\n{\"yes\":true,\"translation\":\"Wanted suspect in Berlin\",\"category_id\":\"wanted_suspect\"}\n```") + if err != nil { + t.Fatal(err) + } + if !got.Yes || got.Translation != "Wanted suspect in Berlin" || got.CategoryID != "wanted_suspect" { + t.Fatalf("unexpected response %#v", got) + } +} + +func TestBatchLLMFiltersAndOverridesCategory(t *testing.T) { + cfg := config.Default() + cfg.AlertLLMModel = "gpt-test" + items := []parse.FeedItem{{Title: "Titulo", Link: "https://example.test/a"}} + classified, err := BatchLLM(context.Background(), cfg, fakeCompleter{content: `{"yes":true,"translation":"Missing child in Madrid","category_id":"missing_person"}`}, "public_appeal", items) + if err != nil { + t.Fatal(err) + } + if len(classified) != 1 { + t.Fatalf("expected 1 classified item, got %d", len(classified)) + } + if classified[0].Item.Title != "Missing child in Madrid" || classified[0].Category != "missing_person" { + t.Fatalf("unexpected classified item %#v", classified[0]) + } +} + +func TestBatchLLMDropsNoise(t *testing.T) { + cfg := config.Default() + items := []parse.FeedItem{{Title: "General update", Link: "https://example.test/a"}} + classified, err := BatchLLM(context.Background(), cfg, fakeCompleter{content: `{"yes":false,"translation":"","category_id":""}`}, "public_appeal", items) + if err != nil { + t.Fatal(err) + } + if len(classified) != 0 { + t.Fatalf("expected no classified items, got %d", len(classified)) + } +} diff --git a/internal/collector/vet/client.go b/internal/collector/vet/client.go new file mode 100644 index 0000000..87c8c27 --- /dev/null +++ b/internal/collector/vet/client.go @@ -0,0 +1,117 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package vet + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + "time" + + "github.com/scalytics/euosint/internal/collector/config" +) + +type Client struct { + httpClient *http.Client + baseURL string + apiKey string + model string + provider string + temperature float64 +} + +func NewClient(cfg config.Config) *Client { + timeout := time.Duration(cfg.HTTPTimeoutMS) * time.Millisecond + if timeout <= 0 { + timeout = 30 * time.Second + } + return &Client{ + httpClient: &http.Client{Timeout: timeout}, + baseURL: strings.TrimSpace(cfg.VettingBaseURL), + apiKey: strings.TrimSpace(cfg.VettingAPIKey), + model: strings.TrimSpace(cfg.VettingModel), + provider: strings.TrimSpace(cfg.VettingProvider), + temperature: cfg.VettingTemperature, + } +} + +type Message struct { + Role string `json:"role"` + Content string `json:"content"` +} + +type chatRequest struct { + Model string `json:"model"` + Messages []Message `json:"messages"` + Temperature float64 `json:"temperature,omitempty"` +} + +type chatResponse struct { + Choices []struct { + Message struct { + Content string `json:"content"` + } `json:"message"` + } `json:"choices"` +} + +func (c *Client) Complete(ctx context.Context, messages []Message) (string, error) { + reqBody, err := json.Marshal(chatRequest{ + Model: c.model, + Messages: messages, + Temperature: c.temperature, + }) + if err != nil { + return "", fmt.Errorf("marshal source vetting request: %w", err) + } + + req, err := http.NewRequestWithContext(ctx, http.MethodPost, completionsURL(c.baseURL), bytes.NewReader(reqBody)) + if err != nil { + return "", fmt.Errorf("build source vetting request: %w", err) + } + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Accept", "application/json") + if c.apiKey != "" { + req.Header.Set("Authorization", "Bearer "+c.apiKey) + } + if c.provider != "" { + req.Header.Set("X-EUOSINT-Provider", c.provider) + } + + res, err := c.httpClient.Do(req) + if err != nil { + return "", fmt.Errorf("request source vetting completion: %w", err) + } + defer res.Body.Close() + body, err := io.ReadAll(res.Body) + if err != nil { + return "", fmt.Errorf("read source vetting response: %w", err) + } + if res.StatusCode < 200 || res.StatusCode >= 300 { + return "", fmt.Errorf("source vetting endpoint status %d: %s", res.StatusCode, strings.TrimSpace(string(body))) + } + + var parsed chatResponse + if err := json.Unmarshal(body, &parsed); err != nil { + return "", fmt.Errorf("decode source vetting response: %w", err) + } + if len(parsed.Choices) == 0 { + return "", fmt.Errorf("source vetting response returned no choices") + } + return strings.TrimSpace(parsed.Choices[0].Message.Content), nil +} + +func completionsURL(baseURL string) string { + baseURL = strings.TrimRight(strings.TrimSpace(baseURL), "/") + if baseURL == "" { + return "https://api.openai.com/v1/chat/completions" + } + if strings.HasSuffix(baseURL, "/chat/completions") { + return baseURL + } + return baseURL + "/chat/completions" +} diff --git a/internal/collector/vet/client_test.go b/internal/collector/vet/client_test.go new file mode 100644 index 0000000..23c8865 --- /dev/null +++ b/internal/collector/vet/client_test.go @@ -0,0 +1,64 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package vet + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "testing" + + "github.com/scalytics/euosint/internal/collector/config" +) + +func TestClientCompleteUsesOpenAICompatibleEndpoint(t *testing.T) { + var gotAuth string + var gotModel string + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/v1/chat/completions" { + t.Fatalf("unexpected path %s", r.URL.Path) + } + gotAuth = r.Header.Get("Authorization") + var payload map[string]any + if err := json.NewDecoder(r.Body).Decode(&payload); err != nil { + t.Fatal(err) + } + gotModel, _ = payload["model"].(string) + _ = json.NewEncoder(w).Encode(map[string]any{ + "choices": []map[string]any{ + {"message": map[string]any{"content": `{"approve":true}`}}, + }, + }) + })) + defer server.Close() + + cfg := config.Default() + cfg.VettingBaseURL = server.URL + "/v1" + cfg.VettingAPIKey = "secret" + cfg.VettingModel = "gpt-test" + client := NewClient(cfg) + content, err := client.Complete(context.Background(), []Message{{Role: "user", Content: "test"}}) + if err != nil { + t.Fatal(err) + } + if gotAuth != "Bearer secret" { + t.Fatalf("expected bearer auth header, got %q", gotAuth) + } + if gotModel != "gpt-test" { + t.Fatalf("expected model gpt-test, got %q", gotModel) + } + if content != `{"approve":true}` { + t.Fatalf("unexpected content %q", content) + } +} + +func TestCompletionsURLNormalizesBase(t *testing.T) { + if got := completionsURL("http://localhost:11434/v1"); got != "http://localhost:11434/v1/chat/completions" { + t.Fatalf("unexpected ollama/vllm url %q", got) + } + if got := completionsURL("https://gateway.example/openai/v1/chat/completions"); got != "https://gateway.example/openai/v1/chat/completions" { + t.Fatalf("unexpected passthrough url %q", got) + } +} diff --git a/internal/collector/vet/source.go b/internal/collector/vet/source.go new file mode 100644 index 0000000..0c4d178 --- /dev/null +++ b/internal/collector/vet/source.go @@ -0,0 +1,178 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package vet + +import ( + "context" + "encoding/json" + "fmt" + "regexp" + "strings" + + "github.com/scalytics/euosint/internal/collector/config" + "github.com/scalytics/euosint/internal/collector/parse" +) + +type Sample struct { + Title string `json:"title"` + Link string `json:"link"` + Summary string `json:"summary,omitempty"` + Tags []string `json:"tags,omitempty"` +} + +type Input struct { + AuthorityName string `json:"authority_name"` + AuthorityType string `json:"authority_type"` + Category string `json:"category"` + Country string `json:"country"` + CountryCode string `json:"country_code"` + URL string `json:"url"` + BaseURL string `json:"base_url"` + FeedType string `json:"feed_type"` + Samples []Sample `json:"samples"` +} + +type Verdict struct { + Approve bool `json:"approve"` + PromotionStatus string `json:"promotion_status"` + Level string `json:"level"` + MissionTags []string `json:"mission_tags"` + SourceQuality float64 `json:"source_quality"` + OperationalRelevance float64 `json:"operational_relevance"` + Reason string `json:"reason"` +} + +type Vetter struct { + client *Client + model string +} + +func New(cfg config.Config) *Vetter { + return &Vetter{client: NewClient(cfg), model: cfg.VettingModel} +} + +func (v *Vetter) Evaluate(ctx context.Context, input Input) (Verdict, error) { + if reason, reject := deterministicReject(input); reject { + return Verdict{ + Approve: false, + PromotionStatus: "rejected", + Level: "local", + MissionTags: nil, + SourceQuality: 0.1, + OperationalRelevance: 0.1, + Reason: reason, + }, nil + } + + payload, err := json.MarshalIndent(input, "", " ") + if err != nil { + return Verdict{}, fmt.Errorf("marshal source vetting input: %w", err) + } + + content, err := v.client.Complete(ctx, []Message{ + { + Role: "system", + Content: "You vet intelligence source candidates. Approve only operationally relevant sources: supranational, federal, or national level sources that publish actionable intelligence, wanted/missing/public appeals, cyber advisories, humanitarian security, crisis, war, organized crime, fraud, terrorism, or public-safety intelligence. Reject generic PR, speeches, institutional updates, local police, municipal news, or low-signal information. Return strict JSON only.", + }, + { + Role: "user", + Content: "Evaluate this discovered source and return JSON with keys approve, promotion_status, level, mission_tags, source_quality, operational_relevance, reason.\n\n" + string(payload), + }, + }) + if err != nil { + return Verdict{}, err + } + + verdict, err := decodeVerdict(content) + if err != nil { + return Verdict{}, err + } + verdict.normalize() + return verdict, nil +} + +func SamplesFromFeedItems(items []parse.FeedItem, limit int) []Sample { + if limit <= 0 || limit > len(items) { + limit = len(items) + } + samples := make([]Sample, 0, limit) + for _, item := range items[:limit] { + samples = append(samples, Sample{ + Title: strings.TrimSpace(item.Title), + Link: strings.TrimSpace(item.Link), + Summary: strings.TrimSpace(item.Summary), + Tags: append([]string(nil), item.Tags...), + }) + } + return samples +} + +var jsonBlockRe = regexp.MustCompile(`(?s)\{.*\}`) + +func decodeVerdict(content string) (Verdict, error) { + content = strings.TrimSpace(content) + if match := jsonBlockRe.FindString(content); match != "" { + content = match + } + var verdict Verdict + if err := json.Unmarshal([]byte(content), &verdict); err != nil { + return Verdict{}, fmt.Errorf("decode source vetting verdict: %w", err) + } + return verdict, nil +} + +func (v *Verdict) normalize() { + v.PromotionStatus = strings.ToLower(strings.TrimSpace(v.PromotionStatus)) + switch v.PromotionStatus { + case "active", "validated", "rejected": + default: + if v.Approve { + v.PromotionStatus = "active" + } else { + v.PromotionStatus = "rejected" + } + } + v.Level = strings.ToLower(strings.TrimSpace(v.Level)) + switch v.Level { + case "international", "supranational", "federal", "national", "regional", "local": + default: + v.Level = "national" + } + v.SourceQuality = clamp01(v.SourceQuality) + v.OperationalRelevance = clamp01(v.OperationalRelevance) + if !v.Approve { + v.PromotionStatus = "rejected" + } +} + +func clamp01(v float64) float64 { + if v < 0 { + return 0 + } + if v > 1 { + return 1 + } + return v +} + +func deterministicReject(input Input) (string, bool) { + hay := strings.ToLower(strings.Join([]string{ + input.AuthorityName, + input.AuthorityType, + input.Category, + input.URL, + input.BaseURL, + }, " ")) + for _, needle := range []string{ + "municipal", "municipality", "city of ", "county ", "sheriff", "police department", "local police", + } { + if strings.Contains(hay, needle) { + return "deterministic reject: local or municipal source", true + } + } + if len(input.Samples) == 0 { + return "deterministic reject: no sample items to assess", true + } + return "", false +} diff --git a/internal/collector/vet/source_test.go b/internal/collector/vet/source_test.go new file mode 100644 index 0000000..fe8688d --- /dev/null +++ b/internal/collector/vet/source_test.go @@ -0,0 +1,41 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package vet + +import ( + "testing" + + "github.com/scalytics/euosint/internal/collector/parse" +) + +func TestDecodeVerdictExtractsJSONBlock(t *testing.T) { + verdict, err := decodeVerdict("```json\n{\"approve\":true,\"promotion_status\":\"active\",\"level\":\"federal\",\"source_quality\":0.9,\"operational_relevance\":0.8,\"mission_tags\":[\"organized_crime\"],\"reason\":\"high signal\"}\n```") + if err != nil { + t.Fatal(err) + } + verdict.normalize() + if !verdict.Approve || verdict.PromotionStatus != "active" || verdict.Level != "federal" { + t.Fatalf("unexpected verdict %#v", verdict) + } +} + +func TestDeterministicRejectsLocalAndMissingSamples(t *testing.T) { + if _, reject := deterministicReject(Input{AuthorityName: "City of Valletta Police Department", Samples: []Sample{{Title: "x"}}}); !reject { + t.Fatal("expected local police deterministic reject") + } + if _, reject := deterministicReject(Input{AuthorityName: "Europol", Samples: nil}); !reject { + t.Fatal("expected no-sample deterministic reject") + } +} + +func TestSamplesFromFeedItemsHonorsLimit(t *testing.T) { + items := []parse.FeedItem{ + {Title: "One", Link: "https://one"}, + {Title: "Two", Link: "https://two"}, + } + samples := SamplesFromFeedItems(items, 1) + if len(samples) != 1 || samples[0].Title != "One" { + t.Fatalf("unexpected samples %#v", samples) + } +} diff --git a/internal/sourcedb/db.go b/internal/sourcedb/db.go new file mode 100644 index 0000000..0c7211c --- /dev/null +++ b/internal/sourcedb/db.go @@ -0,0 +1,1088 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package sourcedb + +import ( + "context" + "database/sql" + _ "embed" + "encoding/json" + "fmt" + "os" + "path/filepath" + "sort" + "strings" + + _ "modernc.org/sqlite" + + "github.com/scalytics/euosint/internal/collector/model" +) + +//go:embed schema.sql +var schemaSQL string + +type DB struct { + sql *sql.DB +} + +type CandidateInput struct { + DiscoveredURL string + DiscoveredVia string + Status string + LanguageCode string + Category string + AuthorityType string + Country string + CountryCode string + Notes string +} + +func Open(path string) (*DB, error) { + if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { + return nil, fmt.Errorf("create source DB directory: %w", err) + } + db, err := sql.Open("sqlite", path) + if err != nil { + return nil, fmt.Errorf("open sqlite source DB: %w", err) + } + return &DB{sql: db}, nil +} + +func (db *DB) Close() error { + if db == nil || db.sql == nil { + return nil + } + return db.sql.Close() +} + +func (db *DB) Init(ctx context.Context) error { + if _, err := db.sql.ExecContext(ctx, schemaSQL); err != nil { + return fmt.Errorf("init source DB schema: %w", err) + } + for _, stmt := range []string{ + `ALTER TABLE agencies ADD COLUMN level TEXT NOT NULL DEFAULT 'national'`, + `ALTER TABLE agencies ADD COLUMN mission_tags_json TEXT NOT NULL DEFAULT '[]'`, + `ALTER TABLE agencies ADD COLUMN operational_relevance REAL NOT NULL DEFAULT 0`, + `ALTER TABLE sources ADD COLUMN source_quality REAL NOT NULL DEFAULT 0`, + `ALTER TABLE sources ADD COLUMN promotion_status TEXT NOT NULL DEFAULT 'candidate'`, + `ALTER TABLE sources ADD COLUMN rejection_reason TEXT NOT NULL DEFAULT ''`, + `ALTER TABLE sources ADD COLUMN is_mirror INTEGER NOT NULL DEFAULT 0`, + `ALTER TABLE sources ADD COLUMN preferred_source_rank INTEGER NOT NULL DEFAULT 0`, + } { + if _, err := db.sql.ExecContext(ctx, stmt); err != nil && !isDuplicateColumnError(err) { + return fmt.Errorf("migrate source DB schema: %w", err) + } + } + // Backfill live sources from pre-promotion-status databases so existing + // vetted registry rows remain visible after schema migration. + if _, err := db.sql.ExecContext(ctx, ` +UPDATE sources +SET promotion_status = 'active' +WHERE status IN ('active', '') + AND promotion_status = 'candidate' + AND NOT EXISTS ( + SELECT 1 + FROM source_candidates c + WHERE c.discovered_url = sources.feed_url + )`); err != nil { + return fmt.Errorf("backfill source promotion status: %w", err) + } + return nil +} + +func isDuplicateColumnError(err error) bool { + if err == nil { + return false + } + msg := strings.ToLower(err.Error()) + return strings.Contains(msg, "duplicate column name") +} + +func (db *DB) ImportRegistry(ctx context.Context, registryPath string) error { + if err := db.Init(ctx); err != nil { + return err + } + sources, err := loadRegistryJSON(registryPath) + if err != nil { + return err + } + + tx, err := db.sql.BeginTx(ctx, nil) + if err != nil { + return fmt.Errorf("begin import tx: %w", err) + } + defer tx.Rollback() + + if _, err := tx.ExecContext(ctx, `DELETE FROM source_categories`); err != nil { + return fmt.Errorf("clear source_categories: %w", err) + } + if _, err := tx.ExecContext(ctx, `DELETE FROM agency_category_coverage`); err != nil { + return fmt.Errorf("clear agency_category_coverage: %w", err) + } + if _, err := tx.ExecContext(ctx, `DELETE FROM sources`); err != nil { + return fmt.Errorf("clear sources: %w", err) + } + if _, err := tx.ExecContext(ctx, `DELETE FROM agency_aliases`); err != nil { + return fmt.Errorf("clear agency_aliases: %w", err) + } + if _, err := tx.ExecContext(ctx, `DELETE FROM agencies_fts`); err != nil { + return fmt.Errorf("clear agencies_fts: %w", err) + } + if _, err := tx.ExecContext(ctx, `DELETE FROM agencies`); err != nil { + return fmt.Errorf("clear agencies: %w", err) + } + + for _, src := range sources { + agencyID := agencyKey(src.Source) + if err := upsertAgency(ctx, tx, agencyID, src.Source); err != nil { + return err + } + if err := upsertSource(ctx, tx, agencyID, src); err != nil { + return err + } + if err := upsertAgencyCoverage(ctx, tx, agencyID, src.Category); err != nil { + return err + } + if err := upsertAgencyFTS(ctx, tx, agencyID, src.Source); err != nil { + return err + } + } + + if err := tx.Commit(); err != nil { + return fmt.Errorf("commit import tx: %w", err) + } + return nil +} + +func (db *DB) MergeRegistry(ctx context.Context, registryPath string) error { + if err := db.Init(ctx); err != nil { + return err + } + sources, err := loadRegistryJSON(registryPath) + if err != nil { + return err + } + + tx, err := db.sql.BeginTx(ctx, nil) + if err != nil { + return fmt.Errorf("begin merge tx: %w", err) + } + defer tx.Rollback() + + for _, src := range sources { + agencyID := agencyKey(src.Source) + if err := upsertAgency(ctx, tx, agencyID, src.Source); err != nil { + return err + } + if err := upsertSource(ctx, tx, agencyID, src); err != nil { + return err + } + if err := upsertAgencyCoverage(ctx, tx, agencyID, src.Category); err != nil { + return err + } + if err := upsertAgencyFTS(ctx, tx, agencyID, src.Source); err != nil { + return err + } + } + + if err := tx.Commit(); err != nil { + return fmt.Errorf("commit merge tx: %w", err) + } + return nil +} + +func (db *DB) UpsertRegistrySources(ctx context.Context, sources []model.RegistrySource) error { + if err := db.Init(ctx); err != nil { + return err + } + if len(sources) == 0 { + return nil + } + tx, err := db.sql.BeginTx(ctx, nil) + if err != nil { + return fmt.Errorf("begin upsert sources tx: %w", err) + } + defer tx.Rollback() + + for _, src := range sources { + agencyID := agencyKey(src.Source) + if err := upsertAgency(ctx, tx, agencyID, src.Source); err != nil { + return err + } + if err := upsertSource(ctx, tx, agencyID, src); err != nil { + return err + } + if err := upsertAgencyCoverage(ctx, tx, agencyID, src.Category); err != nil { + return err + } + if err := upsertAgencyFTS(ctx, tx, agencyID, src.Source); err != nil { + return err + } + } + + if err := tx.Commit(); err != nil { + return fmt.Errorf("commit upsert sources tx: %w", err) + } + return nil +} + +func (db *DB) LoadActiveSources(ctx context.Context) ([]model.RegistrySource, error) { + rows, err := db.sql.QueryContext(ctx, ` +SELECT + s.id, + s.type, + s.fetch_mode, + s.follow_redirects, + s.feed_url, + s.feed_urls_json, + s.category, + s.region_tag, + s.lat, + s.lng, + s.max_items, + s.include_keywords_json, + s.exclude_keywords_json, + s.source_quality, + s.promotion_status, + s.rejection_reason, + s.is_mirror, + s.preferred_source_rank, + s.reporting_label, + s.reporting_url, + s.reporting_phone, + s.reporting_notes, + a.authority_name, + a.language_code, + a.country, + a.country_code, + a.region, + a.authority_type, + a.base_url, + a.scope, + a.level, + a.parent_agency_id, + a.jurisdiction_name, + a.mission_tags_json, + a.operational_relevance, + a.is_curated, + a.is_high_value +FROM sources s +JOIN agencies a ON a.id = s.agency_id +WHERE s.status IN ('active', '') AND s.promotion_status = 'active' +ORDER BY s.id`) + if err != nil { + return nil, fmt.Errorf("query active sources: %w", err) + } + defer rows.Close() + + out := make([]model.RegistrySource, 0) + for rows.Next() { + var ( + sourceID, sourceType, fetchMode, feedURL, feedURLsJSON, category, regionTag string + includeJSON, excludeJSON, promotionStatus, rejectionReason string + reportingLabel, reportingURL, reportingPhone, reportingNotes string + authorityName, languageCode, country, countryCode, region, authorityType, baseURL string + scope, level, parentAgencyID, jurisdictionName, missionTagsJSON string + followRedirects, isMirror int + isCurated, isHighValue int + lat, lng, sourceQuality, operationalRelevance float64 + maxItems, preferredSourceRank int + ) + if err := rows.Scan( + &sourceID, + &sourceType, + &fetchMode, + &followRedirects, + &feedURL, + &feedURLsJSON, + &category, + ®ionTag, + &lat, + &lng, + &maxItems, + &includeJSON, + &excludeJSON, + &sourceQuality, + &promotionStatus, + &rejectionReason, + &isMirror, + &preferredSourceRank, + &reportingLabel, + &reportingURL, + &reportingPhone, + &reportingNotes, + &authorityName, + &languageCode, + &country, + &countryCode, + ®ion, + &authorityType, + &baseURL, + &scope, + &level, + &parentAgencyID, + &jurisdictionName, + &missionTagsJSON, + &operationalRelevance, + &isCurated, + &isHighValue, + ); err != nil { + return nil, fmt.Errorf("scan active source: %w", err) + } + var feedURLs, includeKeywords, excludeKeywords, missionTags []string + if err := decodeJSONStrings(feedURLsJSON, &feedURLs); err != nil { + return nil, err + } + if err := decodeJSONStrings(includeJSON, &includeKeywords); err != nil { + return nil, err + } + if err := decodeJSONStrings(excludeJSON, &excludeKeywords); err != nil { + return nil, err + } + if err := decodeJSONStrings(missionTagsJSON, &missionTags); err != nil { + return nil, err + } + out = append(out, model.RegistrySource{ + Type: sourceType, + FetchMode: emptyToZero(fetchMode), + FollowRedirects: followRedirects == 1, + FeedURL: feedURL, + FeedURLs: feedURLs, + Category: category, + RegionTag: regionTag, + Lat: lat, + Lng: lng, + MaxItems: maxItems, + IncludeKeywords: includeKeywords, + ExcludeKeywords: excludeKeywords, + SourceQuality: sourceQuality, + PromotionStatus: promotionStatus, + RejectionReason: rejectionReason, + IsMirror: isMirror == 1, + PreferredRank: preferredSourceRank, + Reporting: model.ReportingMetadata{ + Label: reportingLabel, + URL: reportingURL, + Phone: reportingPhone, + Notes: reportingNotes, + }, + Source: model.SourceMetadata{ + SourceID: sourceID, + AuthorityName: authorityName, + Country: country, + CountryCode: countryCode, + Region: region, + AuthorityType: authorityType, + BaseURL: baseURL, + Scope: scope, + Level: level, + ParentAgencyID: parentAgencyID, + JurisdictionName: jurisdictionName, + MissionTags: missionTags, + OperationalRelevance: operationalRelevance, + IsCurated: isCurated == 1, + IsHighValue: isHighValue == 1, + LanguageCode: languageCode, + }, + }) + } + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("iterate active sources: %w", err) + } + return out, nil +} + +func (db *DB) LoadAlerts(ctx context.Context) ([]model.Alert, error) { + if err := db.Init(ctx); err != nil { + return nil, err + } + rows, err := db.sql.QueryContext(ctx, ` +SELECT + alert_id, + source_id, + status, + first_seen, + last_seen, + title, + canonical_url, + category, + severity, + region_tag, + lat, + lng, + freshness_hours, + source_json, + reporting_json, + triage_json +FROM alerts +ORDER BY last_seen DESC`) + if err != nil { + return nil, fmt.Errorf("query alerts: %w", err) + } + defer rows.Close() + + out := make([]model.Alert, 0) + for rows.Next() { + var ( + alert model.Alert + sourceJSON, reportingJSON, triageJSON string + ) + if err := rows.Scan( + &alert.AlertID, + &alert.SourceID, + &alert.Status, + &alert.FirstSeen, + &alert.LastSeen, + &alert.Title, + &alert.CanonicalURL, + &alert.Category, + &alert.Severity, + &alert.RegionTag, + &alert.Lat, + &alert.Lng, + &alert.FreshnessHours, + &sourceJSON, + &reportingJSON, + &triageJSON, + ); err != nil { + return nil, fmt.Errorf("scan alert: %w", err) + } + if err := json.Unmarshal([]byte(sourceJSON), &alert.Source); err != nil { + return nil, fmt.Errorf("decode alert source %s: %w", alert.AlertID, err) + } + if strings.TrimSpace(reportingJSON) != "" && reportingJSON != "{}" { + if err := json.Unmarshal([]byte(reportingJSON), &alert.Reporting); err != nil { + return nil, fmt.Errorf("decode alert reporting %s: %w", alert.AlertID, err) + } + } + if strings.TrimSpace(triageJSON) != "" && triageJSON != "null" { + var triage model.Triage + if err := json.Unmarshal([]byte(triageJSON), &triage); err != nil { + return nil, fmt.Errorf("decode alert triage %s: %w", alert.AlertID, err) + } + alert.Triage = &triage + } + out = append(out, alert) + } + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("iterate alerts: %w", err) + } + return out, nil +} + +func (db *DB) UpsertSourceCandidates(ctx context.Context, candidates []CandidateInput) error { + if err := db.Init(ctx); err != nil { + return err + } + if len(candidates) == 0 { + return nil + } + tx, err := db.sql.BeginTx(ctx, nil) + if err != nil { + return fmt.Errorf("begin candidate upsert tx: %w", err) + } + defer tx.Rollback() + + for _, candidate := range candidates { + discoveredURL := strings.TrimSpace(candidate.DiscoveredURL) + if discoveredURL == "" { + continue + } + status := strings.TrimSpace(candidate.Status) + if status == "" { + status = "candidate" + } + if _, err := tx.ExecContext(ctx, ` +INSERT INTO source_candidates ( + discovered_url, discovered_via, status, language_code, category, authority_type, + country, country_code, checked_at, notes +) VALUES (?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?) +ON CONFLICT(discovered_url) DO UPDATE SET + discovered_via = excluded.discovered_via, + status = excluded.status, + language_code = excluded.language_code, + category = excluded.category, + authority_type = excluded.authority_type, + country = excluded.country, + country_code = excluded.country_code, + checked_at = CURRENT_TIMESTAMP, + notes = excluded.notes +`, discoveredURL, strings.TrimSpace(candidate.DiscoveredVia), status, strings.TrimSpace(candidate.LanguageCode), strings.TrimSpace(candidate.Category), strings.TrimSpace(candidate.AuthorityType), strings.TrimSpace(candidate.Country), strings.ToUpper(strings.TrimSpace(candidate.CountryCode)), strings.TrimSpace(candidate.Notes)); err != nil { + return fmt.Errorf("upsert source candidate %s: %w", discoveredURL, err) + } + } + + if err := tx.Commit(); err != nil { + return fmt.Errorf("commit candidate upsert tx: %w", err) + } + return nil +} + +func (db *DB) SaveAlerts(ctx context.Context, alerts []model.Alert) error { + if err := db.Init(ctx); err != nil { + return err + } + tx, err := db.sql.BeginTx(ctx, nil) + if err != nil { + return fmt.Errorf("begin alert save tx: %w", err) + } + defer tx.Rollback() + + if _, err := tx.ExecContext(ctx, `DELETE FROM alerts`); err != nil { + return fmt.Errorf("clear alerts: %w", err) + } + for _, alert := range alerts { + sourceJSON, _ := json.Marshal(alert.Source) + reportingJSON, _ := json.Marshal(alert.Reporting) + triageJSON, _ := json.Marshal(alert.Triage) + if _, err := tx.ExecContext(ctx, ` +INSERT INTO alerts ( + alert_id, source_id, status, first_seen, last_seen, title, canonical_url, + category, severity, region_tag, lat, lng, freshness_hours, source_json, + reporting_json, triage_json +) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) +ON CONFLICT(alert_id) DO UPDATE SET + source_id = excluded.source_id, + status = excluded.status, + first_seen = excluded.first_seen, + last_seen = excluded.last_seen, + title = excluded.title, + canonical_url = excluded.canonical_url, + category = excluded.category, + severity = excluded.severity, + region_tag = excluded.region_tag, + lat = excluded.lat, + lng = excluded.lng, + freshness_hours = excluded.freshness_hours, + source_json = excluded.source_json, + reporting_json = excluded.reporting_json, + triage_json = excluded.triage_json +`, alert.AlertID, alert.SourceID, alert.Status, alert.FirstSeen, alert.LastSeen, alert.Title, alert.CanonicalURL, alert.Category, alert.Severity, alert.RegionTag, alert.Lat, alert.Lng, alert.FreshnessHours, string(sourceJSON), string(reportingJSON), string(triageJSON)); err != nil { + return fmt.Errorf("upsert alert %s: %w", alert.AlertID, err) + } + } + if err := tx.Commit(); err != nil { + return fmt.Errorf("commit alert save tx: %w", err) + } + return nil +} + +func (db *DB) DeactivateSources(ctx context.Context, reasons map[string]string) error { + if len(reasons) == 0 { + return nil + } + tx, err := db.sql.BeginTx(ctx, nil) + if err != nil { + return fmt.Errorf("begin deactivate tx: %w", err) + } + defer tx.Rollback() + + for sourceID, reason := range reasons { + sourceID = strings.TrimSpace(sourceID) + if sourceID == "" { + continue + } + if _, err := tx.ExecContext(ctx, ` +UPDATE sources +SET status = 'needs_replacement', + last_error = ?, + updated_at = CURRENT_TIMESTAMP +WHERE id = ?`, strings.TrimSpace(reason), sourceID); err != nil { + return fmt.Errorf("deactivate source %s: %w", sourceID, err) + } + } + + if err := tx.Commit(); err != nil { + return fmt.Errorf("commit deactivate tx: %w", err) + } + return nil +} + +func (db *DB) ExportRegistry(ctx context.Context, registryPath string) error { + rows, err := db.sql.QueryContext(ctx, ` +SELECT + s.id, + s.type, + s.fetch_mode, + s.follow_redirects, + s.feed_url, + s.feed_urls_json, + s.category, + s.region_tag, + s.lat, + s.lng, + s.max_items, + s.include_keywords_json, + s.exclude_keywords_json, + s.source_quality, + s.promotion_status, + s.rejection_reason, + s.is_mirror, + s.preferred_source_rank, + s.reporting_label, + s.reporting_url, + s.reporting_phone, + s.reporting_notes, + a.id, + a.authority_name, + a.language_code, + a.country, + a.country_code, + a.region, + a.authority_type, + a.base_url, + a.scope, + a.level, + a.parent_agency_id, + a.jurisdiction_name, + a.mission_tags_json, + a.operational_relevance, + a.is_curated, + a.is_high_value +FROM sources s +JOIN agencies a ON a.id = s.agency_id +WHERE s.status IN ('active', 'candidate', '') AND s.promotion_status != 'rejected' +ORDER BY a.region, a.country, a.authority_name, s.id`) + if err != nil { + return fmt.Errorf("query registry export: %w", err) + } + defer rows.Close() + + exported := make([]model.RegistrySource, 0) + for rows.Next() { + var ( + sourceID, sourceType, fetchMode, feedURL, feedURLsJSON, category, regionTag string + includeJSON, excludeJSON, promotionStatus, rejectionReason string + reportingLabel, reportingURL, reportingPhone, reportingNotes string + agencyID, authorityName, languageCode, country, countryCode, region, authorityType, baseURL string + scope, level, parentAgencyID, jurisdictionName, missionTagsJSON string + followRedirects, isMirror int + isCurated, isHighValue int + lat, lng, sourceQuality, operationalRelevance float64 + maxItems, preferredSourceRank int + ) + if err := rows.Scan( + &sourceID, + &sourceType, + &fetchMode, + &followRedirects, + &feedURL, + &feedURLsJSON, + &category, + ®ionTag, + &lat, + &lng, + &maxItems, + &includeJSON, + &excludeJSON, + &sourceQuality, + &promotionStatus, + &rejectionReason, + &isMirror, + &preferredSourceRank, + &reportingLabel, + &reportingURL, + &reportingPhone, + &reportingNotes, + &agencyID, + &authorityName, + &languageCode, + &country, + &countryCode, + ®ion, + &authorityType, + &baseURL, + &scope, + &level, + &parentAgencyID, + &jurisdictionName, + &missionTagsJSON, + &operationalRelevance, + &isCurated, + &isHighValue, + ); err != nil { + return fmt.Errorf("scan registry export: %w", err) + } + + var feedURLs, includeKeywords, excludeKeywords, missionTags []string + if err := decodeJSONStrings(feedURLsJSON, &feedURLs); err != nil { + return err + } + if err := decodeJSONStrings(includeJSON, &includeKeywords); err != nil { + return err + } + if err := decodeJSONStrings(excludeJSON, &excludeKeywords); err != nil { + return err + } + if err := decodeJSONStrings(missionTagsJSON, &missionTags); err != nil { + return err + } + + exported = append(exported, model.RegistrySource{ + Type: sourceType, + FetchMode: emptyToZero(fetchMode), + FollowRedirects: followRedirects == 1, + FeedURL: feedURL, + FeedURLs: feedURLs, + Category: category, + RegionTag: regionTag, + Lat: lat, + Lng: lng, + MaxItems: maxItems, + IncludeKeywords: includeKeywords, + ExcludeKeywords: excludeKeywords, + SourceQuality: sourceQuality, + PromotionStatus: promotionStatus, + RejectionReason: rejectionReason, + IsMirror: isMirror == 1, + PreferredRank: preferredSourceRank, + Reporting: model.ReportingMetadata{ + Label: reportingLabel, + URL: reportingURL, + Phone: reportingPhone, + Notes: reportingNotes, + }, + Source: model.SourceMetadata{ + SourceID: agencyIDOrSourceID(agencyID, sourceID), + AuthorityName: authorityName, + Country: country, + CountryCode: countryCode, + Region: region, + AuthorityType: authorityType, + BaseURL: baseURL, + Scope: scope, + Level: level, + ParentAgencyID: parentAgencyID, + JurisdictionName: jurisdictionName, + MissionTags: missionTags, + OperationalRelevance: operationalRelevance, + IsCurated: isCurated == 1, + IsHighValue: isHighValue == 1, + LanguageCode: languageCode, + }, + }) + } + if err := rows.Err(); err != nil { + return fmt.Errorf("iterate registry export: %w", err) + } + + sort.Slice(exported, func(i, j int) bool { + if exported[i].Source.Region != exported[j].Source.Region { + return exported[i].Source.Region < exported[j].Source.Region + } + if exported[i].Source.Country != exported[j].Source.Country { + return exported[i].Source.Country < exported[j].Source.Country + } + return exported[i].Source.SourceID < exported[j].Source.SourceID + }) + + data, err := json.MarshalIndent(exported, "", " ") + if err != nil { + return fmt.Errorf("marshal exported registry: %w", err) + } + data = append(data, '\n') + if err := os.WriteFile(registryPath, data, 0o644); err != nil { + return fmt.Errorf("write exported registry: %w", err) + } + return nil +} + +func upsertAgency(ctx context.Context, tx *sql.Tx, agencyID string, meta model.SourceMetadata) error { + missionTagsJSON, _ := json.Marshal(compactStrings(meta.MissionTags...)) + _, err := tx.ExecContext(ctx, ` +INSERT INTO agencies (id, authority_name, language_code, country, country_code, region, authority_type, base_url, scope, level, parent_agency_id, jurisdiction_name, mission_tags_json, operational_relevance, is_curated, is_high_value) +VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) +ON CONFLICT(id) DO UPDATE SET + authority_name = excluded.authority_name, + language_code = excluded.language_code, + country = excluded.country, + country_code = excluded.country_code, + region = excluded.region, + authority_type = excluded.authority_type, + base_url = excluded.base_url, + scope = excluded.scope, + level = excluded.level, + parent_agency_id = excluded.parent_agency_id, + jurisdiction_name = excluded.jurisdiction_name, + mission_tags_json = excluded.mission_tags_json, + operational_relevance = excluded.operational_relevance, + is_curated = excluded.is_curated, + is_high_value = excluded.is_high_value, + updated_at = CURRENT_TIMESTAMP +`, agencyID, meta.AuthorityName, meta.LanguageCode, meta.Country, meta.CountryCode, meta.Region, meta.AuthorityType, meta.BaseURL, fallbackScope(meta.Scope), fallbackLevel(meta.Level, meta.Scope), meta.ParentAgencyID, meta.JurisdictionName, string(missionTagsJSON), defaultOperationalRelevance(meta), boolToInt(meta.IsCurated), boolToInt(meta.IsHighValue)) + if err != nil { + return fmt.Errorf("upsert agency %s: %w", agencyID, err) + } + return nil +} + +func upsertSource(ctx context.Context, tx *sql.Tx, agencyID string, src model.RegistrySource) error { + feedURLsJSON, _ := json.Marshal(src.FeedURLs) + includeJSON, _ := json.Marshal(src.IncludeKeywords) + excludeJSON, _ := json.Marshal(src.ExcludeKeywords) + _, err := tx.ExecContext(ctx, ` +INSERT INTO sources ( + id, agency_id, language_code, type, fetch_mode, follow_redirects, feed_url, feed_urls_json, + category, region_tag, lat, lng, max_items, include_keywords_json, exclude_keywords_json, + source_quality, promotion_status, rejection_reason, is_mirror, preferred_source_rank, + reporting_label, reporting_url, reporting_phone, reporting_notes, status +) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'active') +ON CONFLICT(id) DO UPDATE SET + agency_id = excluded.agency_id, + language_code = excluded.language_code, + type = excluded.type, + fetch_mode = excluded.fetch_mode, + follow_redirects = excluded.follow_redirects, + feed_url = excluded.feed_url, + feed_urls_json = excluded.feed_urls_json, + category = excluded.category, + region_tag = excluded.region_tag, + lat = excluded.lat, + lng = excluded.lng, + max_items = excluded.max_items, + include_keywords_json = excluded.include_keywords_json, + exclude_keywords_json = excluded.exclude_keywords_json, + source_quality = excluded.source_quality, + promotion_status = excluded.promotion_status, + rejection_reason = excluded.rejection_reason, + is_mirror = excluded.is_mirror, + preferred_source_rank = excluded.preferred_source_rank, + reporting_label = excluded.reporting_label, + reporting_url = excluded.reporting_url, + reporting_phone = excluded.reporting_phone, + reporting_notes = excluded.reporting_notes, + status = 'active', + updated_at = CURRENT_TIMESTAMP +`, + src.Source.SourceID, + agencyID, + src.Source.LanguageCode, + src.Type, + src.FetchMode, + boolToInt(src.FollowRedirects), + src.FeedURL, + string(feedURLsJSON), + src.Category, + src.RegionTag, + src.Lat, + src.Lng, + src.MaxItems, + string(includeJSON), + string(excludeJSON), + defaultSourceQuality(src), + defaultPromotionStatus(src), + strings.TrimSpace(src.RejectionReason), + boolToInt(src.IsMirror), + src.PreferredRank, + src.Reporting.Label, + src.Reporting.URL, + src.Reporting.Phone, + src.Reporting.Notes, + ) + if err != nil { + return fmt.Errorf("upsert source %s: %w", src.Source.SourceID, err) + } + if _, err := tx.ExecContext(ctx, `INSERT OR IGNORE INTO source_categories (source_id, category) VALUES (?, ?)`, src.Source.SourceID, src.Category); err != nil { + return fmt.Errorf("upsert source category %s: %w", src.Source.SourceID, err) + } + return nil +} + +func upsertAgencyCoverage(ctx context.Context, tx *sql.Tx, agencyID string, category string) error { + category = strings.TrimSpace(category) + if agencyID == "" || category == "" { + return nil + } + if _, err := tx.ExecContext(ctx, `INSERT OR IGNORE INTO agency_category_coverage (agency_id, category) VALUES (?, ?)`, agencyID, category); err != nil { + return fmt.Errorf("upsert agency coverage %s/%s: %w", agencyID, category, err) + } + return nil +} + +func upsertAgencyFTS(ctx context.Context, tx *sql.Tx, agencyID string, meta model.SourceMetadata) error { + if _, err := tx.ExecContext(ctx, `DELETE FROM agencies_fts WHERE agency_id = ?`, agencyID); err != nil { + return fmt.Errorf("clear agency fts %s: %w", agencyID, err) + } + aliases := strings.Join(compactStrings(meta.SourceID, meta.AuthorityName), " ") + _, err := tx.ExecContext(ctx, ` +INSERT INTO agencies_fts (agency_id, authority_name, aliases, country, country_code, region, authority_type, base_url) +VALUES (?, ?, ?, ?, ?, ?, ?, ?) +`, agencyID, meta.AuthorityName, aliases, meta.Country, meta.CountryCode, meta.Region, meta.AuthorityType, meta.BaseURL) + if err != nil { + return fmt.Errorf("upsert agency fts %s: %w", agencyID, err) + } + return nil +} + +func fallbackScope(scope string) string { + scope = strings.TrimSpace(scope) + if scope == "" { + return "national" + } + return scope +} + +func fallbackLevel(level string, scope string) string { + level = strings.ToLower(strings.TrimSpace(level)) + if level != "" { + return level + } + scope = strings.ToLower(strings.TrimSpace(scope)) + switch scope { + case "international", "supranational", "federal", "national", "regional", "local": + return scope + default: + return "national" + } +} + +func defaultOperationalRelevance(meta model.SourceMetadata) float64 { + if meta.OperationalRelevance > 0 { + return meta.OperationalRelevance + } + score := 0.65 + switch fallbackLevel(meta.Level, meta.Scope) { + case "international": + score = 0.95 + case "supranational": + score = 0.92 + case "federal": + score = 0.9 + case "national": + score = 0.82 + case "regional": + score = 0.45 + case "local": + score = 0.2 + } + if meta.IsHighValue { + score += 0.05 + } + if meta.IsCurated { + score += 0.03 + } + if score > 1 { + score = 1 + } + return score +} + +func defaultSourceQuality(src model.RegistrySource) float64 { + if src.SourceQuality > 0 { + return src.SourceQuality + } + score := 0.72 + switch strings.TrimSpace(src.Type) { + case "rss", "travelwarning-atom": + score = 0.9 + case "kev-json", "interpol-red-json", "interpol-yellow-json", "travelwarning-json": + score = 0.95 + case "html-list": + score = 0.62 + } + if src.Source.IsCurated { + score += 0.03 + } + if src.Source.IsHighValue { + score += 0.03 + } + if src.IsMirror { + score -= 0.1 + } + if score > 1 { + score = 1 + } + return score +} + +func defaultPromotionStatus(src model.RegistrySource) string { + status := strings.ToLower(strings.TrimSpace(src.PromotionStatus)) + if status != "" { + return status + } + level := fallbackLevel(src.Source.Level, src.Source.Scope) + if level == "local" { + return "rejected" + } + if level == "regional" && !src.Source.IsCurated && !src.Source.IsHighValue { + return "validated" + } + return "active" +} + +func decodeJSONStrings(raw string, target *[]string) error { + if strings.TrimSpace(raw) == "" { + *target = nil + return nil + } + if err := json.Unmarshal([]byte(raw), target); err != nil { + return fmt.Errorf("decode string array %q: %w", raw, err) + } + return nil +} + +func compactStrings(values ...string) []string { + out := make([]string, 0, len(values)) + for _, value := range values { + value = strings.TrimSpace(value) + if value != "" { + out = append(out, value) + } + } + return out +} + +func boolToInt(v bool) int { + if v { + return 1 + } + return 0 +} + +func emptyToZero(v string) string { + return strings.TrimSpace(v) +} + +func agencyIDOrSourceID(agencyID, sourceID string) string { + if strings.TrimSpace(agencyID) != "" { + return agencyID + } + return sourceID +} + +func agencyKey(meta model.SourceMetadata) string { + base := strings.ToLower(strings.TrimSpace(meta.AuthorityName)) + base = strings.ReplaceAll(base, "&", " and ") + base = strings.Map(func(r rune) rune { + switch { + case r >= 'a' && r <= 'z': + return r + case r >= '0' && r <= '9': + return r + default: + return '-' + } + }, base) + base = strings.Trim(base, "-") + base = strings.Join(strings.FieldsFunc(base, func(r rune) bool { return r == '-' }), "-") + if base == "" { + base = strings.ToLower(strings.TrimSpace(meta.SourceID)) + } + if code := strings.ToLower(strings.TrimSpace(meta.CountryCode)); code != "" { + return base + "-" + code + } + return base +} + +func loadRegistryJSON(path string) ([]model.RegistrySource, error) { + data, err := os.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("read registry %s: %w", path, err) + } + var raw []model.RegistrySource + if err := json.Unmarshal(data, &raw); err != nil { + return nil, fmt.Errorf("decode registry %s: %w", path, err) + } + return raw, nil +} diff --git a/internal/sourcedb/db_test.go b/internal/sourcedb/db_test.go new file mode 100644 index 0000000..3b7a149 --- /dev/null +++ b/internal/sourcedb/db_test.go @@ -0,0 +1,282 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package sourcedb + +import ( + "context" + "os" + "path/filepath" + "testing" + "time" + + "github.com/scalytics/euosint/internal/collector/model" +) + +func TestImportAndExportRegistry(t *testing.T) { + dir := t.TempDir() + registryPath := filepath.Join(dir, "registry.json") + dbPath := filepath.Join(dir, "sources.db") + content := `[ + {"type":"rss","feed_url":"https://one.example/feed","category":"cyber_advisory","region_tag":"EU","source":{"source_id":"agency-one-feed","authority_name":"Agency One","country":"France","country_code":"FR","region":"Europe","authority_type":"cert","base_url":"https://one.example"}}, + {"type":"rss","feed_url":"https://one.example/alerts","category":"public_appeal","region_tag":"EU","source":{"source_id":"agency-one-alerts","authority_name":"Agency One","country":"France","country_code":"FR","region":"Europe","authority_type":"cert","base_url":"https://one.example"}} + ]` + if err := os.WriteFile(registryPath, []byte(content), 0o644); err != nil { + t.Fatal(err) + } + + db, err := Open(dbPath) + if err != nil { + t.Fatal(err) + } + defer db.Close() + + if err := db.ImportRegistry(context.Background(), registryPath); err != nil { + t.Fatal(err) + } + sources, err := db.LoadActiveSources(context.Background()) + if err != nil { + t.Fatal(err) + } + if len(sources) != 2 { + t.Fatalf("expected 2 active sources, got %d", len(sources)) + } + + exportPath := filepath.Join(dir, "exported.json") + if err := db.ExportRegistry(context.Background(), exportPath); err != nil { + t.Fatal(err) + } + if _, err := os.Stat(exportPath); err != nil { + t.Fatalf("expected exported registry file: %v", err) + } +} + +func TestDeactivateSourcesRemovesThemFromActiveLoad(t *testing.T) { + dir := t.TempDir() + registryPath := filepath.Join(dir, "registry.json") + dbPath := filepath.Join(dir, "sources.db") + content := `[ + {"type":"rss","feed_url":"https://one.example/feed","category":"cyber_advisory","source":{"source_id":"agency-one-feed","authority_name":"Agency One","country":"France","country_code":"FR","region":"Europe","authority_type":"cert","base_url":"https://one.example"}} + ]` + if err := os.WriteFile(registryPath, []byte(content), 0o644); err != nil { + t.Fatal(err) + } + + db, err := Open(dbPath) + if err != nil { + t.Fatal(err) + } + defer db.Close() + if err := db.ImportRegistry(context.Background(), registryPath); err != nil { + t.Fatal(err) + } + if err := db.DeactivateSources(context.Background(), map[string]string{ + "agency-one-feed": "fetch https://one.example/feed: status 404", + }); err != nil { + t.Fatal(err) + } + sources, err := db.LoadActiveSources(context.Background()) + if err != nil { + t.Fatal(err) + } + if len(sources) != 0 { + t.Fatalf("expected deactivated source to be removed from active load, got %d", len(sources)) + } +} + +func TestScopeAndCurationMetadataRoundTrip(t *testing.T) { + dir := t.TempDir() + registryPath := filepath.Join(dir, "registry.json") + dbPath := filepath.Join(dir, "sources.db") + content := `[ + {"type":"rss","feed_url":"https://example.test/feed","category":"wanted_suspect","source_quality":0.97,"promotion_status":"active","source":{"source_id":"europol","authority_name":"Europol","country":"Netherlands","country_code":"NL","region":"Europe","authority_type":"police","base_url":"https://www.europol.europa.eu","scope":"supranational","level":"supranational","mission_tags":["organized_crime","wanted_suspect"],"operational_relevance":0.98,"is_curated":true,"is_high_value":true,"language_code":"en"}} + ]` + if err := os.WriteFile(registryPath, []byte(content), 0o644); err != nil { + t.Fatal(err) + } + + db, err := Open(dbPath) + if err != nil { + t.Fatal(err) + } + defer db.Close() + if err := db.ImportRegistry(context.Background(), registryPath); err != nil { + t.Fatal(err) + } + + sources, err := db.LoadActiveSources(context.Background()) + if err != nil { + t.Fatal(err) + } + if len(sources) != 1 { + t.Fatalf("expected 1 active source, got %d", len(sources)) + } + if sources[0].Source.Scope != "supranational" { + t.Fatalf("expected scope to round-trip, got %q", sources[0].Source.Scope) + } + if !sources[0].Source.IsCurated || !sources[0].Source.IsHighValue { + t.Fatalf("expected curated/high-value flags to round-trip: %#v", sources[0].Source) + } + if sources[0].Source.LanguageCode != "en" { + t.Fatalf("expected language code to round-trip, got %q", sources[0].Source.LanguageCode) + } + if sources[0].Source.Level != "supranational" { + t.Fatalf("expected level to round-trip, got %q", sources[0].Source.Level) + } + if sources[0].PromotionStatus != "active" { + t.Fatalf("expected promotion_status to round-trip, got %q", sources[0].PromotionStatus) + } + if sources[0].SourceQuality != 0.97 { + t.Fatalf("expected source_quality to round-trip, got %v", sources[0].SourceQuality) + } + if len(sources[0].Source.MissionTags) != 2 { + t.Fatalf("expected mission tags to round-trip, got %#v", sources[0].Source.MissionTags) + } +} + +func TestMergeRegistryAddsCuratedSeedWithoutReplacingExistingSources(t *testing.T) { + dir := t.TempDir() + baseRegistryPath := filepath.Join(dir, "base.json") + seedRegistryPath := filepath.Join(dir, "seed.json") + dbPath := filepath.Join(dir, "sources.db") + + base := `[ + {"type":"rss","feed_url":"https://example.test/base","category":"cyber_advisory","source":{"source_id":"base-source","authority_name":"Base Source","country":"France","country_code":"FR","region":"Europe","authority_type":"cert","base_url":"https://example.test"}} + ]` + seed := `[ + {"type":"rss","feed_url":"https://example.test/seed","category":"wanted_suspect","source":{"source_id":"seed-source","authority_name":"Seed Source","country":"United States","country_code":"US","region":"North America","authority_type":"police","base_url":"https://example.test","scope":"national","is_curated":true,"is_high_value":true,"language_code":"en"}} + ]` + if err := os.WriteFile(baseRegistryPath, []byte(base), 0o644); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(seedRegistryPath, []byte(seed), 0o644); err != nil { + t.Fatal(err) + } + + db, err := Open(dbPath) + if err != nil { + t.Fatal(err) + } + defer db.Close() + if err := db.ImportRegistry(context.Background(), baseRegistryPath); err != nil { + t.Fatal(err) + } + if err := db.MergeRegistry(context.Background(), seedRegistryPath); err != nil { + t.Fatal(err) + } + + sources, err := db.LoadActiveSources(context.Background()) + if err != nil { + t.Fatal(err) + } + if len(sources) != 2 { + t.Fatalf("expected merged source count 2, got %d", len(sources)) + } +} + +func TestSaveAndLoadAlertsReplacesMaterializedStateWithoutDuplicates(t *testing.T) { + dir := t.TempDir() + dbPath := filepath.Join(dir, "sources.db") + + db, err := Open(dbPath) + if err != nil { + t.Fatal(err) + } + defer db.Close() + + firstSeen := time.Date(2026, 3, 16, 10, 0, 0, 0, time.UTC).Format(time.RFC3339) + lastSeen := time.Date(2026, 3, 16, 10, 15, 0, 0, time.UTC).Format(time.RFC3339) + alerts := []model.Alert{ + { + AlertID: "alpha", + SourceID: "source-one", + Title: "Alpha alert", + CanonicalURL: "https://example.test/a", + FirstSeen: firstSeen, + LastSeen: lastSeen, + Status: "active", + Category: "cyber_advisory", + Severity: "high", + RegionTag: "EU", + Source: model.SourceMetadata{ + SourceID: "source-one", + AuthorityName: "Source One", + Country: "France", + CountryCode: "FR", + Region: "Europe", + AuthorityType: "cert", + BaseURL: "https://example.test", + }, + }, + } + if err := db.SaveAlerts(context.Background(), alerts); err != nil { + t.Fatal(err) + } + if err := db.SaveAlerts(context.Background(), alerts); err != nil { + t.Fatal(err) + } + + loaded, err := db.LoadAlerts(context.Background()) + if err != nil { + t.Fatal(err) + } + if len(loaded) != 1 { + t.Fatalf("expected exactly 1 persisted alert, got %d", len(loaded)) + } + if loaded[0].AlertID != "alpha" { + t.Fatalf("expected alert alpha, got %q", loaded[0].AlertID) + } + if loaded[0].FirstSeen != firstSeen { + t.Fatalf("expected first_seen %q, got %q", firstSeen, loaded[0].FirstSeen) + } +} + +func TestUpsertSourceCandidatesDeduplicatesByURL(t *testing.T) { + dir := t.TempDir() + dbPath := filepath.Join(dir, "sources.db") + + db, err := Open(dbPath) + if err != nil { + t.Fatal(err) + } + defer db.Close() + + inputs := []CandidateInput{ + { + DiscoveredURL: "https://example.test/feed", + DiscoveredVia: "first.org", + Status: "candidate", + Category: "cyber_advisory", + AuthorityType: "cert", + Country: "France", + CountryCode: "FR", + Notes: "Agency One", + }, + { + DiscoveredURL: "https://example.test/feed", + DiscoveredVia: "replacement-queue", + Status: "candidate", + Category: "public_appeal", + AuthorityType: "police", + Country: "France", + CountryCode: "FR", + Notes: "Agency One Revised", + }, + } + if err := db.UpsertSourceCandidates(context.Background(), inputs); err != nil { + t.Fatal(err) + } + + row := db.sql.QueryRowContext(context.Background(), `SELECT COUNT(*), discovered_via, category, authority_type, notes FROM source_candidates WHERE discovered_url = ?`, "https://example.test/feed") + var count int + var discoveredVia, category, authorityType, notes string + if err := row.Scan(&count, &discoveredVia, &category, &authorityType, ¬es); err != nil { + t.Fatal(err) + } + if count != 1 { + t.Fatalf("expected 1 candidate row, got %d", count) + } + if discoveredVia != "replacement-queue" || category != "public_appeal" || authorityType != "police" || notes != "Agency One Revised" { + t.Fatalf("unexpected candidate row values: via=%q category=%q authority=%q notes=%q", discoveredVia, category, authorityType, notes) + } +} diff --git a/internal/sourcedb/schema.sql b/internal/sourcedb/schema.sql new file mode 100644 index 0000000..7ed97fc --- /dev/null +++ b/internal/sourcedb/schema.sql @@ -0,0 +1,161 @@ +CREATE TABLE IF NOT EXISTS agencies ( + id TEXT PRIMARY KEY, + authority_name TEXT NOT NULL, + language_code TEXT NOT NULL DEFAULT '', + country TEXT NOT NULL, + country_code TEXT NOT NULL, + region TEXT NOT NULL, + authority_type TEXT NOT NULL, + base_url TEXT NOT NULL, + scope TEXT NOT NULL DEFAULT 'national', + level TEXT NOT NULL DEFAULT 'national', + parent_agency_id TEXT NOT NULL DEFAULT '', + jurisdiction_name TEXT NOT NULL DEFAULT '', + mission_tags_json TEXT NOT NULL DEFAULT '[]', + operational_relevance REAL NOT NULL DEFAULT 0, + is_curated INTEGER NOT NULL DEFAULT 0, + is_high_value INTEGER NOT NULL DEFAULT 0, + created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE IF NOT EXISTS agency_aliases ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + agency_id TEXT NOT NULL, + alias TEXT NOT NULL, + alias_type TEXT NOT NULL DEFAULT 'short_name', + UNIQUE(agency_id, alias), + FOREIGN KEY (agency_id) REFERENCES agencies(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS sources ( + id TEXT PRIMARY KEY, + agency_id TEXT NOT NULL, + language_code TEXT NOT NULL DEFAULT '', + type TEXT NOT NULL, + fetch_mode TEXT NOT NULL DEFAULT '', + follow_redirects INTEGER NOT NULL DEFAULT 0, + feed_url TEXT NOT NULL, + feed_urls_json TEXT NOT NULL DEFAULT '[]', + category TEXT NOT NULL, + region_tag TEXT NOT NULL DEFAULT '', + lat REAL NOT NULL DEFAULT 0, + lng REAL NOT NULL DEFAULT 0, + max_items INTEGER NOT NULL DEFAULT 0, + include_keywords_json TEXT NOT NULL DEFAULT '[]', + exclude_keywords_json TEXT NOT NULL DEFAULT '[]', + source_quality REAL NOT NULL DEFAULT 0, + promotion_status TEXT NOT NULL DEFAULT 'candidate', + rejection_reason TEXT NOT NULL DEFAULT '', + is_mirror INTEGER NOT NULL DEFAULT 0, + preferred_source_rank INTEGER NOT NULL DEFAULT 0, + reporting_label TEXT NOT NULL DEFAULT '', + reporting_url TEXT NOT NULL DEFAULT '', + reporting_phone TEXT NOT NULL DEFAULT '', + reporting_notes TEXT NOT NULL DEFAULT '', + status TEXT NOT NULL DEFAULT 'active', + last_http_status INTEGER, + last_ok_at TEXT, + last_error TEXT, + last_error_class TEXT, + created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (agency_id) REFERENCES agencies(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS source_categories ( + source_id TEXT NOT NULL, + category TEXT NOT NULL, + PRIMARY KEY (source_id, category), + FOREIGN KEY (source_id) REFERENCES sources(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS agency_category_coverage ( + agency_id TEXT NOT NULL, + category TEXT NOT NULL, + PRIMARY KEY (agency_id, category), + FOREIGN KEY (agency_id) REFERENCES agencies(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS source_checks ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + source_id TEXT NOT NULL, + checked_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, + http_status INTEGER, + final_url TEXT NOT NULL DEFAULT '', + content_type TEXT NOT NULL DEFAULT '', + ok INTEGER NOT NULL DEFAULT 0, + error TEXT NOT NULL DEFAULT '', + error_class TEXT NOT NULL DEFAULT '', + FOREIGN KEY (source_id) REFERENCES sources(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS source_candidates ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + agency_id TEXT, + discovered_url TEXT NOT NULL, + discovered_via TEXT NOT NULL DEFAULT '', + status TEXT NOT NULL DEFAULT 'candidate', + language_code TEXT NOT NULL DEFAULT '', + category TEXT NOT NULL DEFAULT '', + authority_type TEXT NOT NULL DEFAULT '', + country TEXT NOT NULL DEFAULT '', + country_code TEXT NOT NULL DEFAULT '', + checked_at TEXT, + notes TEXT NOT NULL DEFAULT '', + UNIQUE(discovered_url), + FOREIGN KEY (agency_id) REFERENCES agencies(id) ON DELETE SET NULL +); + +CREATE TABLE IF NOT EXISTS source_term_overrides ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + source_id TEXT NOT NULL, + category TEXT NOT NULL, + language_code TEXT NOT NULL DEFAULT '', + term TEXT NOT NULL, + term_type TEXT NOT NULL, + created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, + UNIQUE(source_id, category, language_code, term, term_type), + FOREIGN KEY (source_id) REFERENCES sources(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS alerts ( + alert_id TEXT PRIMARY KEY, + source_id TEXT NOT NULL, + status TEXT NOT NULL, + first_seen TEXT NOT NULL, + last_seen TEXT NOT NULL, + title TEXT NOT NULL, + canonical_url TEXT NOT NULL, + category TEXT NOT NULL, + severity TEXT NOT NULL, + region_tag TEXT NOT NULL, + lat REAL NOT NULL DEFAULT 0, + lng REAL NOT NULL DEFAULT 0, + freshness_hours INTEGER NOT NULL DEFAULT 0, + source_json TEXT NOT NULL, + reporting_json TEXT NOT NULL DEFAULT '{}', + triage_json TEXT NOT NULL DEFAULT 'null' +); + +CREATE INDEX IF NOT EXISTS idx_sources_agency_id ON sources(agency_id); +CREATE INDEX IF NOT EXISTS idx_sources_status ON sources(status); +CREATE INDEX IF NOT EXISTS idx_sources_feed_url ON sources(feed_url); +CREATE INDEX IF NOT EXISTS idx_source_checks_source_id_checked_at ON source_checks(source_id, checked_at DESC); +CREATE INDEX IF NOT EXISTS idx_source_candidates_status ON source_candidates(status); +CREATE UNIQUE INDEX IF NOT EXISTS idx_source_candidates_discovered_url ON source_candidates(discovered_url); +CREATE INDEX IF NOT EXISTS idx_source_term_overrides_source_id ON source_term_overrides(source_id); +CREATE INDEX IF NOT EXISTS idx_agency_category_coverage_category ON agency_category_coverage(category); +CREATE INDEX IF NOT EXISTS idx_alerts_status ON alerts(status); +CREATE INDEX IF NOT EXISTS idx_alerts_source_id ON alerts(source_id); + +CREATE VIRTUAL TABLE IF NOT EXISTS agencies_fts USING fts5( + agency_id UNINDEXED, + authority_name, + aliases, + country, + country_code, + region, + authority_type, + base_url +); diff --git a/package-lock.json b/package-lock.json index fb738bb..5665a0c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,24 +8,22 @@ "name": "euosint", "version": "0.0.0", "dependencies": { - "@types/three": "^0.182.0", "clsx": "^2.1.1", + "leaflet": "^1.9.4", + "leaflet.markercluster": "^1.5.3", "lucide-react": "^0.563.0", "react": "^19.2.0", "react-dom": "^19.2.0", - "react-globe.gl": "^2.37.0", - "tailwind-merge": "^3.4.0", - "three": "^0.182.0", - "topojson-client": "^3.1.0" + "tailwind-merge": "^3.4.0" }, "devDependencies": { "@eslint/js": "^9.39.1", "@tailwindcss/vite": "^4.1.18", + "@types/leaflet": "^1.9.21", + "@types/leaflet.markercluster": "^1.5.6", "@types/node": "^24.10.1", "@types/react": "^19.2.5", "@types/react-dom": "^19.2.3", - "@types/topojson-client": "^3.1.5", - "@types/topojson-specification": "^1.0.5", "@vitejs/plugin-react": "^5.1.1", "eslint": "^9.39.1", "eslint-plugin-react-hooks": "^7.0.1", @@ -275,15 +273,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/runtime": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", - "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/template": { "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", @@ -332,12 +321,6 @@ "node": ">=6.9.0" } }, - "node_modules/@dimforge/rapier3d-compat": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz", - "integrity": "sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==", - "license": "Apache-2.0" - }, "node_modules/@esbuild/aix-ppc64": { "version": "0.27.3", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", @@ -1668,55 +1651,6 @@ "vite": "^5.2.0 || ^6 || ^7" } }, - "node_modules/@turf/boolean-point-in-polygon": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@turf/boolean-point-in-polygon/-/boolean-point-in-polygon-7.3.4.tgz", - "integrity": "sha512-v/4hfyY90Vz9cDgs2GwjQf+Lft8o7mNCLJOTz/iv8SHAIgMMX0czEoIaNVOJr7tBqPqwin1CGwsncrkf5C9n8Q==", - "license": "MIT", - "dependencies": { - "@turf/helpers": "7.3.4", - "@turf/invariant": "7.3.4", - "@types/geojson": "^7946.0.10", - "point-in-polygon-hao": "^1.1.0", - "tslib": "^2.8.1" - }, - "funding": { - "url": "https://opencollective.com/turf" - } - }, - "node_modules/@turf/helpers": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", - "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", - "license": "MIT", - "dependencies": { - "@types/geojson": "^7946.0.10", - "tslib": "^2.8.1" - }, - "funding": { - "url": "https://opencollective.com/turf" - } - }, - "node_modules/@turf/invariant": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", - "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", - "license": "MIT", - "dependencies": { - "@turf/helpers": "7.3.4", - "@types/geojson": "^7946.0.10", - "tslib": "^2.8.1" - }, - "funding": { - "url": "https://opencollective.com/turf" - } - }, - "node_modules/@tweenjs/tween.js": { - "version": "23.1.3", - "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz", - "integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==", - "license": "MIT" - }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -1773,6 +1707,7 @@ "version": "7946.0.16", "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "dev": true, "license": "MIT" }, "node_modules/@types/json-schema": { @@ -1782,6 +1717,26 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/leaflet": { + "version": "1.9.21", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.21.tgz", + "integrity": "sha512-TbAd9DaPGSnzp6QvtYngntMZgcRk+igFELwR2N99XZn7RXUdKgsXMR+28bUO0rPsWp8MIu/f47luLIQuSLYv/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/leaflet.markercluster": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/@types/leaflet.markercluster/-/leaflet.markercluster-1.5.6.tgz", + "integrity": "sha512-I7hZjO2+isVXGYWzKxBp8PsCzAYCJBc29qBdFpquOCkS7zFDqUsUvkEOyQHedsk/Cy5tocQzf+Ndorm5W9YKTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/leaflet": "^1.9" + } + }, "node_modules/@types/node": { "version": "24.10.12", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.12.tgz", @@ -1812,54 +1767,6 @@ "@types/react": "^19.2.0" } }, - "node_modules/@types/stats.js": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.4.tgz", - "integrity": "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==", - "license": "MIT" - }, - "node_modules/@types/three": { - "version": "0.182.0", - "resolved": "https://registry.npmjs.org/@types/three/-/three-0.182.0.tgz", - "integrity": "sha512-WByN9V3Sbwbe2OkWuSGyoqQO8Du6yhYaXtXLoA5FkKTUJorZ+yOHBZ35zUUPQXlAKABZmbYp5oAqpA4RBjtJ/Q==", - "license": "MIT", - "dependencies": { - "@dimforge/rapier3d-compat": "~0.12.0", - "@tweenjs/tween.js": "~23.1.3", - "@types/stats.js": "*", - "@types/webxr": ">=0.5.17", - "@webgpu/types": "*", - "fflate": "~0.8.2", - "meshoptimizer": "~0.22.0" - } - }, - "node_modules/@types/topojson-client": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@types/topojson-client/-/topojson-client-3.1.5.tgz", - "integrity": "sha512-C79rySTyPxnQNNguTZNI1Ct4D7IXgvyAs3p9HPecnl6mNrJ5+UhvGNYcZfpROYV2lMHI48kJPxwR+F9C6c7nmw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/geojson": "*", - "@types/topojson-specification": "*" - } - }, - "node_modules/@types/topojson-specification": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/topojson-specification/-/topojson-specification-1.0.5.tgz", - "integrity": "sha512-C7KvcQh+C2nr6Y2Ub4YfgvWvWCgP2nOQMtfhlnwsRL4pYmmwzBS7HclGiS87eQfDOU/DLQpX6GEscviaz4yLIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/geojson": "*" - } - }, - "node_modules/@types/webxr": { - "version": "0.5.24", - "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.24.tgz", - "integrity": "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==", - "license": "MIT" - }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.54.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.54.0.tgz", @@ -2150,21 +2057,6 @@ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, - "node_modules/@webgpu/types": { - "version": "0.1.69", - "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.69.tgz", - "integrity": "sha512-RPmm6kgRbI8e98zSD3RVACvnuktIja5+yLgDAkTmxLr90BEwdTXRQWNLF3ETTTyH/8mKhznZuN5AveXYFEsMGQ==", - "license": "BSD-3-Clause" - }, - "node_modules/accessor-fn": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/accessor-fn/-/accessor-fn-1.5.3.tgz", - "integrity": "sha512-rkAofCwe/FvYFUlMB0v0gWmhqtfAtV1IUkdPbfhTUyYniu5LrC0A0UJkTH0Jv3S8SvwkmfuAlY+mQIJATdocMA==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", @@ -2367,12 +2259,6 @@ "dev": true, "license": "MIT" }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "license": "MIT" - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2409,180 +2295,6 @@ "dev": true, "license": "MIT" }, - "node_modules/d3-array": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", - "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", - "license": "ISC", - "dependencies": { - "internmap": "1 - 2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-delaunay": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", - "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", - "license": "ISC", - "dependencies": { - "delaunator": "5" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-format": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", - "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-geo": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", - "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", - "license": "ISC", - "dependencies": { - "d3-array": "2.5.0 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-geo-voronoi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/d3-geo-voronoi/-/d3-geo-voronoi-2.1.0.tgz", - "integrity": "sha512-kqE4yYuOjPbKdBXG0xztCacPwkVSK2REF1opSNrnqqtXJmNcM++UbwQ8SxvwP6IQTj9RvIjjK4qeiVsEfj0Z2Q==", - "license": "ISC", - "dependencies": { - "d3-array": "3", - "d3-delaunay": "6", - "d3-geo": "3", - "d3-tricontour": "1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-octree": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-octree/-/d3-octree-1.1.0.tgz", - "integrity": "sha512-F8gPlqpP+HwRPMO/8uOu5wjH110+6q4cgJvgJT6vlpy3BEaDIKlTZrgHKZSp/i1InRpVfh4puY/kvL6MxK930A==", - "license": "MIT" - }, - "node_modules/d3-scale": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", - "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", - "license": "ISC", - "dependencies": { - "d3-array": "2.10.0 - 3", - "d3-format": "1 - 3", - "d3-interpolate": "1.2.0 - 3", - "d3-time": "2.1.1 - 3", - "d3-time-format": "2 - 4" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-scale-chromatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", - "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3", - "d3-interpolate": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-selection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", - "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", - "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", - "license": "ISC", - "dependencies": { - "d3-array": "2 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time-format": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", - "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", - "license": "ISC", - "dependencies": { - "d3-time": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-tricontour": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-tricontour/-/d3-tricontour-1.1.0.tgz", - "integrity": "sha512-G7gHKj89n2owmkGb6WX6ixcnQ0Kf/0wpa9VIh9DGdbHu8wdrlaHU4ir3/bFNERl8N8nn4G7e7qbtBG8N9caihQ==", - "license": "ISC", - "dependencies": { - "d3-delaunay": "6", - "d3-scale": "4" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/data-bind-mapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/data-bind-mapper/-/data-bind-mapper-1.0.3.tgz", - "integrity": "sha512-QmU3lyEnbENQPo0M1F9BMu4s6cqNNp8iJA+b/HP2sSb7pf3dxwF3+EP1eO69rwBfH9kFJ1apmzrtogAmVt2/Xw==", - "license": "MIT", - "dependencies": { - "accessor-fn": "1" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -2608,15 +2320,6 @@ "dev": true, "license": "MIT" }, - "node_modules/delaunator": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", - "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", - "license": "ISC", - "dependencies": { - "robust-predicates": "^3.0.2" - } - }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", @@ -2627,12 +2330,6 @@ "node": ">=8" } }, - "node_modules/earcut": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.2.tgz", - "integrity": "sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==", - "license": "ISC" - }, "node_modules/electron-to-chromium": { "version": "1.5.286", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", @@ -2942,12 +2639,6 @@ } } }, - "node_modules/fflate": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", - "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", - "license": "MIT" - }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -2999,29 +2690,6 @@ "dev": true, "license": "ISC" }, - "node_modules/float-tooltip": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/float-tooltip/-/float-tooltip-1.7.5.tgz", - "integrity": "sha512-/kXzuDnnBqyyWyhDMH7+PfP8J/oXiAavGzcRxASOMRHFuReDtofizLLJsf7nnDLAfEaMW4pVWaXrAjtnglpEkg==", - "license": "MIT", - "dependencies": { - "d3-selection": "2 - 3", - "kapsule": "^1.16", - "preact": "10" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/frame-ticker": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/frame-ticker/-/frame-ticker-1.0.3.tgz", - "integrity": "sha512-E0X2u2JIvbEMrqEg5+4BpTqaD22OwojJI63K7MdKHdncjtAhGRbCR8nJCr2vwEt9NWBPCPcu70X9smPviEBy8Q==", - "license": "MIT", - "dependencies": { - "simplesignal": "^2.1.6" - } - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -3073,23 +2741,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globe.gl": { - "version": "2.45.0", - "resolved": "https://registry.npmjs.org/globe.gl/-/globe.gl-2.45.0.tgz", - "integrity": "sha512-fjkLHVBrnbESkUgklTd4UbcGLciu4nIl49IIi1hclLjI6MU3ASu6JYmf/K5qwPf7I+tNOauQRr4i5Y28JTtHQg==", - "license": "MIT", - "dependencies": { - "@tweenjs/tween.js": "18 - 25", - "accessor-fn": "1", - "kapsule": "^1.16", - "three": ">=0.154 <1", - "three-globe": "^2.45", - "three-render-objects": "^1.40" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -3097,17 +2748,6 @@ "dev": true, "license": "ISC" }, - "node_modules/h3-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/h3-js/-/h3-js-4.4.0.tgz", - "integrity": "sha512-DvJh07MhGgY2KcC4OeZc8SSyA+ZXpdvoh6uCzGpoKvWtZxJB+g6VXXC1+eWYkaMIsLz7J/ErhOalHCpcs1KYog==", - "license": "Apache-2.0", - "engines": { - "node": ">=4", - "npm": ">=3", - "yarn": ">=1.3.0" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -3172,24 +2812,6 @@ "node": ">=0.8.19" } }, - "node_modules/index-array-by": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/index-array-by/-/index-array-by-1.4.2.tgz", - "integrity": "sha512-SP23P27OUKzXWEC/TOyWlwLviofQkCSCKONnc62eItjp69yCZZPqDQtr3Pw5gJDnPeUMqExmKydNZaJO0FU9pw==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/internmap": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", - "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -3220,15 +2842,6 @@ "dev": true, "license": "ISC" }, - "node_modules/jerrypick": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/jerrypick/-/jerrypick-1.1.2.tgz", - "integrity": "sha512-YKnxXEekXKzhpf7CLYA0A+oDP8V0OhICNCr5lv96FvSsDEmrb0GKM776JgQvHTMjr7DTTPEVv/1Ciaw0uEWzBA==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, "node_modules/jiti": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", @@ -3243,6 +2856,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -3305,18 +2919,6 @@ "node": ">=6" } }, - "node_modules/kapsule": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/kapsule/-/kapsule-1.16.3.tgz", - "integrity": "sha512-4+5mNNf4vZDSwPhKprKwz3330iisPrb08JyMgbsdFrimBCKNHecua/WBwvVg3n7vwx0C1ARjfhwIpbrbd9n5wg==", - "license": "MIT", - "dependencies": { - "lodash-es": "4" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -3327,6 +2929,21 @@ "json-buffer": "3.0.1" } }, + "node_modules/leaflet": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", + "license": "BSD-2-Clause" + }, + "node_modules/leaflet.markercluster": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/leaflet.markercluster/-/leaflet.markercluster-1.5.3.tgz", + "integrity": "sha512-vPTw/Bndq7eQHjLBVlWpnGeLa3t+3zGiuM7fJwCkiMFq+nmRuG3RI3f7f4N4TDX7T4NpbAXpR2+NTRSEGfCSeA==", + "license": "MIT", + "peerDependencies": { + "leaflet": "^1.3.1" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -3618,12 +3235,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash-es": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", - "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", - "license": "MIT" - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -3631,18 +3242,6 @@ "dev": true, "license": "MIT" }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "license": "MIT", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -3672,12 +3271,6 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/meshoptimizer": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.22.0.tgz", - "integrity": "sha512-IebiK79sqIy+E4EgOr+CAw+Ke8hAspXKzBd0JdgEmPHiAwmvEj2S4h1rfvo+o/BnfEYd/jAOg5IeeIjzlzSnDg==", - "license": "MIT" - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3731,15 +3324,6 @@ "dev": true, "license": "MIT" }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -3843,27 +3427,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/point-in-polygon-hao": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/point-in-polygon-hao/-/point-in-polygon-hao-1.2.4.tgz", - "integrity": "sha512-x2pcvXeqhRHlNRdhLs/tgFapAbSSe86wa/eqmj1G6pWftbEs5aVRJhRGM6FYSUERKu0PjekJzMq0gsI2XyiclQ==", - "license": "MIT", - "dependencies": { - "robust-predicates": "^3.0.2" - } - }, - "node_modules/polished": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz", - "integrity": "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.17.8" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -3893,16 +3456,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/preact": { - "version": "10.28.3", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.28.3.tgz", - "integrity": "sha512-tCmoRkPQLpBeWzpmbhryairGnhW9tKV6c6gr/w+RhoRoKEJwsjzipwp//1oCpGPOchvSLaAPlpcJi9MwMmoPyA==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/preact" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3913,17 +3466,6 @@ "node": ">= 0.8.0" } }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -3955,44 +3497,6 @@ "react": "^19.2.4" } }, - "node_modules/react-globe.gl": { - "version": "2.37.0", - "resolved": "https://registry.npmjs.org/react-globe.gl/-/react-globe.gl-2.37.0.tgz", - "integrity": "sha512-nN1FDOJBhFvWfKrOY0SnkDuA8wk9FSTBN0HFfAdTqqcFM5R+OXBIxK0BM6t8n3oNVYpEJVxEzjYFwLyk4BC7Cw==", - "license": "MIT", - "dependencies": { - "globe.gl": "^2.45", - "prop-types": "15", - "react-kapsule": "^2.5" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "react": "*" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "license": "MIT" - }, - "node_modules/react-kapsule": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/react-kapsule/-/react-kapsule-2.5.7.tgz", - "integrity": "sha512-kifAF4ZPD77qZKc4CKLmozq6GY1sBzPEJTIJb0wWFK6HsePJatK3jXplZn2eeAt3x67CDozgi7/rO8fNQ/AL7A==", - "license": "MIT", - "dependencies": { - "jerrypick": "^1.1.1" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "react": ">=16.13.1" - } - }, "node_modules/react-refresh": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", @@ -4013,12 +3517,6 @@ "node": ">=4" } }, - "node_modules/robust-predicates": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", - "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", - "license": "Unlicense" - }, "node_modules/rollup": { "version": "4.57.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", @@ -4103,12 +3601,6 @@ "node": ">=8" } }, - "node_modules/simplesignal": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/simplesignal/-/simplesignal-2.1.7.tgz", - "integrity": "sha512-PEo2qWpUke7IMhlqiBxrulIFvhJRLkl1ih52Rwa+bPjzhJepcd4GIjn2RiQmFSx3dQvsEAgF0/lXMwMN7vODaA==", - "license": "MIT" - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -4176,123 +3668,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/three": { - "version": "0.182.0", - "resolved": "https://registry.npmjs.org/three/-/three-0.182.0.tgz", - "integrity": "sha512-GbHabT+Irv+ihI1/f5kIIsZ+Ef9Sl5A1Y7imvS5RQjWgtTPfPnZ43JmlYI7NtCRDK9zir20lQpfg8/9Yd02OvQ==", - "license": "MIT" - }, - "node_modules/three-conic-polygon-geometry": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/three-conic-polygon-geometry/-/three-conic-polygon-geometry-2.1.2.tgz", - "integrity": "sha512-NaP3RWLJIyPGI+zyaZwd0Yj6rkoxm4FJHqAX1Enb4L64oNYLCn4bz1ESgOEYavgcUwCNYINu1AgEoUBJr1wZcA==", - "license": "MIT", - "dependencies": { - "@turf/boolean-point-in-polygon": "^7.2", - "d3-array": "1 - 3", - "d3-geo": "1 - 3", - "d3-geo-voronoi": "2", - "d3-scale": "1 - 4", - "delaunator": "5", - "earcut": "3" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "three": ">=0.72.0" - } - }, - "node_modules/three-geojson-geometry": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/three-geojson-geometry/-/three-geojson-geometry-2.1.1.tgz", - "integrity": "sha512-dC7bF3ri1goDcihYhzACHOBQqu7YNNazYLa2bSydVIiJUb3jDFojKSy+gNj2pMkqZNSVjssSmdY9zlmnhEpr1w==", - "license": "MIT", - "dependencies": { - "d3-geo": "1 - 3", - "d3-interpolate": "1 - 3", - "earcut": "3" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "three": ">=0.72.0" - } - }, - "node_modules/three-globe": { - "version": "2.45.0", - "resolved": "https://registry.npmjs.org/three-globe/-/three-globe-2.45.0.tgz", - "integrity": "sha512-Ur6BVkezvmHnvsEg8fbq6gIscSZtknSQMWwDRbiJ95o6OSDjDbGTc4oO6nP7mOM9aAA3YrF7YZyOwSkP4T56QA==", - "license": "MIT", - "dependencies": { - "@tweenjs/tween.js": "18 - 25", - "accessor-fn": "1", - "d3-array": "3", - "d3-color": "3", - "d3-geo": "3", - "d3-interpolate": "3", - "d3-scale": "4", - "d3-scale-chromatic": "3", - "data-bind-mapper": "1", - "frame-ticker": "1", - "h3-js": "4", - "index-array-by": "1", - "kapsule": "^1.16", - "three-conic-polygon-geometry": "2", - "three-geojson-geometry": "2", - "three-slippy-map-globe": "1", - "tinycolor2": "1" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "three": ">=0.154" - } - }, - "node_modules/three-render-objects": { - "version": "1.40.4", - "resolved": "https://registry.npmjs.org/three-render-objects/-/three-render-objects-1.40.4.tgz", - "integrity": "sha512-Ukpu1pei3L5r809izvjsZxwuRcYLiyn6Uvy3lZ9bpMTdvj3i6PeX6w++/hs2ZS3KnEzGjb6YvTvh4UQuwHTDJg==", - "license": "MIT", - "dependencies": { - "@tweenjs/tween.js": "18 - 25", - "accessor-fn": "1", - "float-tooltip": "^1.7", - "kapsule": "^1.16", - "polished": "4" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "three": ">=0.168" - } - }, - "node_modules/three-slippy-map-globe": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/three-slippy-map-globe/-/three-slippy-map-globe-1.0.4.tgz", - "integrity": "sha512-am8A4PP38AfTdrhXBDucwPRHLTbBl93yhpjIs56K1TLs9VuUWzg68oim4Dibs9QC1riXbj5SoBp/okA1VN9eYg==", - "license": "MIT", - "dependencies": { - "d3-geo": "1 - 3", - "d3-octree": "^1.1", - "d3-scale": "1 - 4" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "three": ">=0.154" - } - }, - "node_modules/tinycolor2": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", - "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", - "license": "MIT" - }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -4310,20 +3685,6 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/topojson-client": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz", - "integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==", - "license": "ISC", - "dependencies": { - "commander": "2" - }, - "bin": { - "topo2geo": "bin/topo2geo", - "topomerge": "bin/topomerge", - "topoquantize": "bin/topoquantize" - } - }, "node_modules/ts-api-utils": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", @@ -4341,7 +3702,9 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "dev": true, + "license": "0BSD", + "optional": true }, "node_modules/type-check": { "version": "0.4.0", @@ -4742,11 +4105,6 @@ "@babel/helper-plugin-utils": "^7.27.1" } }, - "@babel/runtime": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", - "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==" - }, "@babel/template": { "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", @@ -4783,11 +4141,6 @@ "@babel/helper-validator-identifier": "^7.28.5" } }, - "@dimforge/rapier3d-compat": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz", - "integrity": "sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==" - }, "@esbuild/aix-ppc64": { "version": "0.27.3", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", @@ -5458,42 +4811,6 @@ "tailwindcss": "4.1.18" } }, - "@turf/boolean-point-in-polygon": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@turf/boolean-point-in-polygon/-/boolean-point-in-polygon-7.3.4.tgz", - "integrity": "sha512-v/4hfyY90Vz9cDgs2GwjQf+Lft8o7mNCLJOTz/iv8SHAIgMMX0czEoIaNVOJr7tBqPqwin1CGwsncrkf5C9n8Q==", - "requires": { - "@turf/helpers": "7.3.4", - "@turf/invariant": "7.3.4", - "@types/geojson": "^7946.0.10", - "point-in-polygon-hao": "^1.1.0", - "tslib": "^2.8.1" - } - }, - "@turf/helpers": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.4.tgz", - "integrity": "sha512-U/S5qyqgx3WTvg4twaH0WxF3EixoTCfDsmk98g1E3/5e2YKp7JKYZdz0vivsS5/UZLJeZDEElOSFH4pUgp+l7g==", - "requires": { - "@types/geojson": "^7946.0.10", - "tslib": "^2.8.1" - } - }, - "@turf/invariant": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-7.3.4.tgz", - "integrity": "sha512-88Eo4va4rce9sNZs6XiMJowWkikM3cS2TBhaCKlU+GFHdNf8PFEpiU42VDU8q5tOF6/fu21Rvlke5odgOGW4AQ==", - "requires": { - "@turf/helpers": "7.3.4", - "@types/geojson": "^7946.0.10", - "tslib": "^2.8.1" - } - }, - "@tweenjs/tween.js": { - "version": "23.1.3", - "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz", - "integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==" - }, "@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -5544,7 +4861,8 @@ "@types/geojson": { "version": "7946.0.16", "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", - "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==" + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "dev": true }, "@types/json-schema": { "version": "7.0.15", @@ -5552,6 +4870,24 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "@types/leaflet": { + "version": "1.9.21", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.21.tgz", + "integrity": "sha512-TbAd9DaPGSnzp6QvtYngntMZgcRk+igFELwR2N99XZn7RXUdKgsXMR+28bUO0rPsWp8MIu/f47luLIQuSLYv/w==", + "dev": true, + "requires": { + "@types/geojson": "*" + } + }, + "@types/leaflet.markercluster": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/@types/leaflet.markercluster/-/leaflet.markercluster-1.5.6.tgz", + "integrity": "sha512-I7hZjO2+isVXGYWzKxBp8PsCzAYCJBc29qBdFpquOCkS7zFDqUsUvkEOyQHedsk/Cy5tocQzf+Ndorm5W9YKTQ==", + "dev": true, + "requires": { + "@types/leaflet": "^1.9" + } + }, "@types/node": { "version": "24.10.12", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.12.tgz", @@ -5577,49 +4913,6 @@ "dev": true, "requires": {} }, - "@types/stats.js": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.4.tgz", - "integrity": "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==" - }, - "@types/three": { - "version": "0.182.0", - "resolved": "https://registry.npmjs.org/@types/three/-/three-0.182.0.tgz", - "integrity": "sha512-WByN9V3Sbwbe2OkWuSGyoqQO8Du6yhYaXtXLoA5FkKTUJorZ+yOHBZ35zUUPQXlAKABZmbYp5oAqpA4RBjtJ/Q==", - "requires": { - "@dimforge/rapier3d-compat": "~0.12.0", - "@tweenjs/tween.js": "~23.1.3", - "@types/stats.js": "*", - "@types/webxr": ">=0.5.17", - "@webgpu/types": "*", - "fflate": "~0.8.2", - "meshoptimizer": "~0.22.0" - } - }, - "@types/topojson-client": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@types/topojson-client/-/topojson-client-3.1.5.tgz", - "integrity": "sha512-C79rySTyPxnQNNguTZNI1Ct4D7IXgvyAs3p9HPecnl6mNrJ5+UhvGNYcZfpROYV2lMHI48kJPxwR+F9C6c7nmw==", - "dev": true, - "requires": { - "@types/geojson": "*", - "@types/topojson-specification": "*" - } - }, - "@types/topojson-specification": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/topojson-specification/-/topojson-specification-1.0.5.tgz", - "integrity": "sha512-C7KvcQh+C2nr6Y2Ub4YfgvWvWCgP2nOQMtfhlnwsRL4pYmmwzBS7HclGiS87eQfDOU/DLQpX6GEscviaz4yLIQ==", - "dev": true, - "requires": { - "@types/geojson": "*" - } - }, - "@types/webxr": { - "version": "0.5.24", - "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.24.tgz", - "integrity": "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==" - }, "@typescript-eslint/eslint-plugin": { "version": "8.54.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.54.0.tgz", @@ -5783,16 +5076,6 @@ "react-refresh": "^0.18.0" } }, - "@webgpu/types": { - "version": "0.1.69", - "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.69.tgz", - "integrity": "sha512-RPmm6kgRbI8e98zSD3RVACvnuktIja5+yLgDAkTmxLr90BEwdTXRQWNLF3ETTTyH/8mKhznZuN5AveXYFEsMGQ==" - }, - "accessor-fn": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/accessor-fn/-/accessor-fn-1.5.3.tgz", - "integrity": "sha512-rkAofCwe/FvYFUlMB0v0gWmhqtfAtV1IUkdPbfhTUyYniu5LrC0A0UJkTH0Jv3S8SvwkmfuAlY+mQIJATdocMA==" - }, "acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", @@ -5910,11 +5193,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -5944,123 +5222,6 @@ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "dev": true }, - "d3-array": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", - "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", - "requires": { - "internmap": "1 - 2" - } - }, - "d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==" - }, - "d3-delaunay": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", - "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", - "requires": { - "delaunator": "5" - } - }, - "d3-format": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", - "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==" - }, - "d3-geo": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", - "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", - "requires": { - "d3-array": "2.5.0 - 3" - } - }, - "d3-geo-voronoi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/d3-geo-voronoi/-/d3-geo-voronoi-2.1.0.tgz", - "integrity": "sha512-kqE4yYuOjPbKdBXG0xztCacPwkVSK2REF1opSNrnqqtXJmNcM++UbwQ8SxvwP6IQTj9RvIjjK4qeiVsEfj0Z2Q==", - "requires": { - "d3-array": "3", - "d3-delaunay": "6", - "d3-geo": "3", - "d3-tricontour": "1" - } - }, - "d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", - "requires": { - "d3-color": "1 - 3" - } - }, - "d3-octree": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-octree/-/d3-octree-1.1.0.tgz", - "integrity": "sha512-F8gPlqpP+HwRPMO/8uOu5wjH110+6q4cgJvgJT6vlpy3BEaDIKlTZrgHKZSp/i1InRpVfh4puY/kvL6MxK930A==" - }, - "d3-scale": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", - "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", - "requires": { - "d3-array": "2.10.0 - 3", - "d3-format": "1 - 3", - "d3-interpolate": "1.2.0 - 3", - "d3-time": "2.1.1 - 3", - "d3-time-format": "2 - 4" - } - }, - "d3-scale-chromatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", - "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", - "requires": { - "d3-color": "1 - 3", - "d3-interpolate": "1 - 3" - } - }, - "d3-selection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", - "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==" - }, - "d3-time": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", - "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", - "requires": { - "d3-array": "2 - 3" - } - }, - "d3-time-format": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", - "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", - "requires": { - "d3-time": "1 - 3" - } - }, - "d3-tricontour": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-tricontour/-/d3-tricontour-1.1.0.tgz", - "integrity": "sha512-G7gHKj89n2owmkGb6WX6ixcnQ0Kf/0wpa9VIh9DGdbHu8wdrlaHU4ir3/bFNERl8N8nn4G7e7qbtBG8N9caihQ==", - "requires": { - "d3-delaunay": "6", - "d3-scale": "4" - } - }, - "data-bind-mapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/data-bind-mapper/-/data-bind-mapper-1.0.3.tgz", - "integrity": "sha512-QmU3lyEnbENQPo0M1F9BMu4s6cqNNp8iJA+b/HP2sSb7pf3dxwF3+EP1eO69rwBfH9kFJ1apmzrtogAmVt2/Xw==", - "requires": { - "accessor-fn": "1" - } - }, "debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -6076,25 +5237,12 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "delaunator": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", - "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", - "requires": { - "robust-predicates": "^3.0.2" - } - }, "detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true }, - "earcut": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.2.tgz", - "integrity": "sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==" - }, "electron-to-chromium": { "version": "1.5.286", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", @@ -6301,11 +5449,6 @@ "dev": true, "requires": {} }, - "fflate": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", - "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==" - }, "file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -6341,24 +5484,6 @@ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true }, - "float-tooltip": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/float-tooltip/-/float-tooltip-1.7.5.tgz", - "integrity": "sha512-/kXzuDnnBqyyWyhDMH7+PfP8J/oXiAavGzcRxASOMRHFuReDtofizLLJsf7nnDLAfEaMW4pVWaXrAjtnglpEkg==", - "requires": { - "d3-selection": "2 - 3", - "kapsule": "^1.16", - "preact": "10" - } - }, - "frame-ticker": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/frame-ticker/-/frame-ticker-1.0.3.tgz", - "integrity": "sha512-E0X2u2JIvbEMrqEg5+4BpTqaD22OwojJI63K7MdKHdncjtAhGRbCR8nJCr2vwEt9NWBPCPcu70X9smPviEBy8Q==", - "requires": { - "simplesignal": "^2.1.6" - } - }, "fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -6387,30 +5512,12 @@ "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", "dev": true }, - "globe.gl": { - "version": "2.45.0", - "resolved": "https://registry.npmjs.org/globe.gl/-/globe.gl-2.45.0.tgz", - "integrity": "sha512-fjkLHVBrnbESkUgklTd4UbcGLciu4nIl49IIi1hclLjI6MU3ASu6JYmf/K5qwPf7I+tNOauQRr4i5Y28JTtHQg==", - "requires": { - "@tweenjs/tween.js": "18 - 25", - "accessor-fn": "1", - "kapsule": "^1.16", - "three": ">=0.154 <1", - "three-globe": "^2.45", - "three-render-objects": "^1.40" - } - }, "graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "h3-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/h3-js/-/h3-js-4.4.0.tgz", - "integrity": "sha512-DvJh07MhGgY2KcC4OeZc8SSyA+ZXpdvoh6uCzGpoKvWtZxJB+g6VXXC1+eWYkaMIsLz7J/ErhOalHCpcs1KYog==" - }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -6454,16 +5561,6 @@ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true }, - "index-array-by": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/index-array-by/-/index-array-by-1.4.2.tgz", - "integrity": "sha512-SP23P27OUKzXWEC/TOyWlwLviofQkCSCKONnc62eItjp69yCZZPqDQtr3Pw5gJDnPeUMqExmKydNZaJO0FU9pw==" - }, - "internmap": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", - "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==" - }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -6485,11 +5582,6 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, - "jerrypick": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/jerrypick/-/jerrypick-1.1.2.tgz", - "integrity": "sha512-YKnxXEekXKzhpf7CLYA0A+oDP8V0OhICNCr5lv96FvSsDEmrb0GKM776JgQvHTMjr7DTTPEVv/1Ciaw0uEWzBA==" - }, "jiti": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", @@ -6499,7 +5591,8 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true }, "js-yaml": { "version": "4.1.1", @@ -6540,14 +5633,6 @@ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, - "kapsule": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/kapsule/-/kapsule-1.16.3.tgz", - "integrity": "sha512-4+5mNNf4vZDSwPhKprKwz3330iisPrb08JyMgbsdFrimBCKNHecua/WBwvVg3n7vwx0C1ARjfhwIpbrbd9n5wg==", - "requires": { - "lodash-es": "4" - } - }, "keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -6557,6 +5642,17 @@ "json-buffer": "3.0.1" } }, + "leaflet": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==" + }, + "leaflet.markercluster": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/leaflet.markercluster/-/leaflet.markercluster-1.5.3.tgz", + "integrity": "sha512-vPTw/Bndq7eQHjLBVlWpnGeLa3t+3zGiuM7fJwCkiMFq+nmRuG3RI3f7f4N4TDX7T4NpbAXpR2+NTRSEGfCSeA==", + "requires": {} + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -6673,25 +5769,12 @@ "p-locate": "^5.0.0" } }, - "lodash-es": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", - "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==" - }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -6716,11 +5799,6 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "meshoptimizer": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.22.0.tgz", - "integrity": "sha512-IebiK79sqIy+E4EgOr+CAw+Ke8hAspXKzBd0JdgEmPHiAwmvEj2S4h1rfvo+o/BnfEYd/jAOg5IeeIjzlzSnDg==" - }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -6754,11 +5832,6 @@ "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", "dev": true }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, "optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -6824,22 +5897,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true }, - "point-in-polygon-hao": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/point-in-polygon-hao/-/point-in-polygon-hao-1.2.4.tgz", - "integrity": "sha512-x2pcvXeqhRHlNRdhLs/tgFapAbSSe86wa/eqmj1G6pWftbEs5aVRJhRGM6FYSUERKu0PjekJzMq0gsI2XyiclQ==", - "requires": { - "robust-predicates": "^3.0.2" - } - }, - "polished": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz", - "integrity": "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==", - "requires": { - "@babel/runtime": "^7.17.8" - } - }, "postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -6851,27 +5908,12 @@ "source-map-js": "^1.2.1" } }, - "preact": { - "version": "10.28.3", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.28.3.tgz", - "integrity": "sha512-tCmoRkPQLpBeWzpmbhryairGnhW9tKV6c6gr/w+RhoRoKEJwsjzipwp//1oCpGPOchvSLaAPlpcJi9MwMmoPyA==" - }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, - "prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, "punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -6891,29 +5933,6 @@ "scheduler": "^0.27.0" } }, - "react-globe.gl": { - "version": "2.37.0", - "resolved": "https://registry.npmjs.org/react-globe.gl/-/react-globe.gl-2.37.0.tgz", - "integrity": "sha512-nN1FDOJBhFvWfKrOY0SnkDuA8wk9FSTBN0HFfAdTqqcFM5R+OXBIxK0BM6t8n3oNVYpEJVxEzjYFwLyk4BC7Cw==", - "requires": { - "globe.gl": "^2.45", - "prop-types": "15", - "react-kapsule": "^2.5" - } - }, - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "react-kapsule": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/react-kapsule/-/react-kapsule-2.5.7.tgz", - "integrity": "sha512-kifAF4ZPD77qZKc4CKLmozq6GY1sBzPEJTIJb0wWFK6HsePJatK3jXplZn2eeAt3x67CDozgi7/rO8fNQ/AL7A==", - "requires": { - "jerrypick": "^1.1.1" - } - }, "react-refresh": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", @@ -6926,11 +5945,6 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, - "robust-predicates": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", - "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" - }, "rollup": { "version": "4.57.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", @@ -6992,11 +6006,6 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, - "simplesignal": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/simplesignal/-/simplesignal-2.1.7.tgz", - "integrity": "sha512-PEo2qWpUke7IMhlqiBxrulIFvhJRLkl1ih52Rwa+bPjzhJepcd4GIjn2RiQmFSx3dQvsEAgF0/lXMwMN7vODaA==" - }, "source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -7035,86 +6044,6 @@ "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", "dev": true }, - "three": { - "version": "0.182.0", - "resolved": "https://registry.npmjs.org/three/-/three-0.182.0.tgz", - "integrity": "sha512-GbHabT+Irv+ihI1/f5kIIsZ+Ef9Sl5A1Y7imvS5RQjWgtTPfPnZ43JmlYI7NtCRDK9zir20lQpfg8/9Yd02OvQ==" - }, - "three-conic-polygon-geometry": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/three-conic-polygon-geometry/-/three-conic-polygon-geometry-2.1.2.tgz", - "integrity": "sha512-NaP3RWLJIyPGI+zyaZwd0Yj6rkoxm4FJHqAX1Enb4L64oNYLCn4bz1ESgOEYavgcUwCNYINu1AgEoUBJr1wZcA==", - "requires": { - "@turf/boolean-point-in-polygon": "^7.2", - "d3-array": "1 - 3", - "d3-geo": "1 - 3", - "d3-geo-voronoi": "2", - "d3-scale": "1 - 4", - "delaunator": "5", - "earcut": "3" - } - }, - "three-geojson-geometry": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/three-geojson-geometry/-/three-geojson-geometry-2.1.1.tgz", - "integrity": "sha512-dC7bF3ri1goDcihYhzACHOBQqu7YNNazYLa2bSydVIiJUb3jDFojKSy+gNj2pMkqZNSVjssSmdY9zlmnhEpr1w==", - "requires": { - "d3-geo": "1 - 3", - "d3-interpolate": "1 - 3", - "earcut": "3" - } - }, - "three-globe": { - "version": "2.45.0", - "resolved": "https://registry.npmjs.org/three-globe/-/three-globe-2.45.0.tgz", - "integrity": "sha512-Ur6BVkezvmHnvsEg8fbq6gIscSZtknSQMWwDRbiJ95o6OSDjDbGTc4oO6nP7mOM9aAA3YrF7YZyOwSkP4T56QA==", - "requires": { - "@tweenjs/tween.js": "18 - 25", - "accessor-fn": "1", - "d3-array": "3", - "d3-color": "3", - "d3-geo": "3", - "d3-interpolate": "3", - "d3-scale": "4", - "d3-scale-chromatic": "3", - "data-bind-mapper": "1", - "frame-ticker": "1", - "h3-js": "4", - "index-array-by": "1", - "kapsule": "^1.16", - "three-conic-polygon-geometry": "2", - "three-geojson-geometry": "2", - "three-slippy-map-globe": "1", - "tinycolor2": "1" - } - }, - "three-render-objects": { - "version": "1.40.4", - "resolved": "https://registry.npmjs.org/three-render-objects/-/three-render-objects-1.40.4.tgz", - "integrity": "sha512-Ukpu1pei3L5r809izvjsZxwuRcYLiyn6Uvy3lZ9bpMTdvj3i6PeX6w++/hs2ZS3KnEzGjb6YvTvh4UQuwHTDJg==", - "requires": { - "@tweenjs/tween.js": "18 - 25", - "accessor-fn": "1", - "float-tooltip": "^1.7", - "kapsule": "^1.16", - "polished": "4" - } - }, - "three-slippy-map-globe": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/three-slippy-map-globe/-/three-slippy-map-globe-1.0.4.tgz", - "integrity": "sha512-am8A4PP38AfTdrhXBDucwPRHLTbBl93yhpjIs56K1TLs9VuUWzg68oim4Dibs9QC1riXbj5SoBp/okA1VN9eYg==", - "requires": { - "d3-geo": "1 - 3", - "d3-octree": "^1.1", - "d3-scale": "1 - 4" - } - }, - "tinycolor2": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", - "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" - }, "tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -7125,14 +6054,6 @@ "picomatch": "^4.0.3" } }, - "topojson-client": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz", - "integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==", - "requires": { - "commander": "2" - } - }, "ts-api-utils": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", @@ -7143,7 +6064,9 @@ "tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "optional": true }, "type-check": { "version": "0.4.0", diff --git a/package.json b/package.json index cd3847b..1820207 100644 --- a/package.json +++ b/package.json @@ -26,24 +26,22 @@ "docker:run": "sh -c 'if command -v docker-compose >/dev/null 2>&1; then docker-compose up --build; else docker compose up --build; fi'" }, "dependencies": { - "@types/three": "^0.182.0", "clsx": "^2.1.1", + "leaflet": "^1.9.4", + "leaflet.markercluster": "^1.5.3", "lucide-react": "^0.563.0", "react": "^19.2.0", "react-dom": "^19.2.0", - "react-globe.gl": "^2.37.0", - "tailwind-merge": "^3.4.0", - "three": "^0.182.0", - "topojson-client": "^3.1.0" + "tailwind-merge": "^3.4.0" }, "devDependencies": { "@eslint/js": "^9.39.1", "@tailwindcss/vite": "^4.1.18", + "@types/leaflet": "^1.9.21", + "@types/leaflet.markercluster": "^1.5.6", "@types/node": "^24.10.1", "@types/react": "^19.2.5", "@types/react-dom": "^19.2.3", - "@types/topojson-client": "^3.1.5", - "@types/topojson-specification": "^1.0.5", "@vitejs/plugin-react": "^5.1.1", "eslint": "^9.39.1", "eslint-plugin-react-hooks": "^7.0.1", diff --git a/registry/category_dictionary.json b/registry/category_dictionary.json new file mode 100644 index 0000000..6ce3447 --- /dev/null +++ b/registry/category_dictionary.json @@ -0,0 +1,250 @@ +{ + "categories": { + "missing_person": { + "default": { + "strong": [ + "missing person", + "missing child", + "amber alert", + "silver alert", + "disappeared person", + "person missing", + "lost child" + ], + "negative": [ + "calendar", + "history", + "institution", + "policy", + "transparency", + "certification", + "department", + "press room" + ], + "url_hints": [ + "/missing", + "/missing-person", + "/missing-children", + "/amber-alert" + ] + }, + "languages": { + "es": { + "strong": ["desaparec", "persona desaparecida", "menor desaparecido", "no localizado", "ubicanos"], + "negative": ["calendario", "historia", "institucion", "transparencia", "certificacion", "oficinas"], + "url_hints": ["/desaparecid", "/desaparec", "/ubicanos"] + }, + "ca": { + "strong": ["persona desapareguda", "desaparegut", "desapareguda", "menor desaparegut"], + "negative": ["calendari", "historia", "institucio", "transparencia"], + "url_hints": ["/desapareg"] + }, + "fr": { + "strong": ["personne disparue", "enfant disparu", "alerte enlèvement", "disparu", "disparue"], + "negative": ["calendrier", "historique", "institution", "transparence"], + "url_hints": ["/disparu", "/disparue"] + }, + "de": { + "strong": ["vermisst", "vermisste person", "vermisstes kind"], + "negative": ["kalender", "geschichte", "institution", "transparenz"], + "url_hints": ["/vermisst"] + }, + "it": { + "strong": ["persona scomparsa", "minore scomparso", "scomparso", "scomparsa"], + "negative": ["calendario", "storia", "istituzione", "trasparenza"], + "url_hints": ["/scompars"] + }, + "pt": { + "strong": ["pessoa desaparecida", "crianca desaparecida", "desaparecido", "desaparecida"], + "negative": ["calendario", "historia", "institucional", "transparencia"], + "url_hints": ["/desaparecid"] + }, + "nl": { + "strong": ["vermiste persoon", "vermist kind", "vermist"], + "negative": ["kalender", "geschiedenis", "instelling", "transparantie"], + "url_hints": ["/vermist"] + }, + "pl": { + "strong": ["osoba zaginiona", "zaginione dziecko", "zaginiony", "zaginiona"], + "url_hints": ["/zagin"] + }, + "ru": { + "strong": ["пропал", "пропала", "без вести", "разыскивается ребенок"], + "url_hints": ["/проп", "/missing"] + }, + "uk": { + "strong": ["зниклий", "зникла", "безвісти", "розшук дитини"], + "url_hints": ["/зник"] + }, + "ar": { + "strong": ["مفقود", "طفل مفقود", "مفقودة"], + "url_hints": ["/مفقود"] + }, + "tr": { + "strong": ["kayıp kişi", "kayıp çocuk", "kayıp"], + "url_hints": ["/kayip", "/kayıp"] + }, + "el": { + "strong": ["αγνοούμενος", "αγνοούμενη", "εξαφανισμένος", "εξαφανισμένη"], + "url_hints": ["/αγνο"] + }, + "zh": { + "strong": ["失踪", "失蹤", "走失", "寻人", "尋人"], + "url_hints": ["/missing", "/尋人", "/寻人"] + }, + "ja": { + "strong": ["行方不明", "失踪", "捜索願", "捜しています"], + "url_hints": ["/missing", "/行方不明"] + }, + "ko": { + "strong": ["실종", "실종자", "실종아동"], + "url_hints": ["/실종"] + }, + "hi": { + "strong": ["लापता", "गुमशुदा", "लापता व्यक्ति", "लापता बच्चा"], + "url_hints": ["/missing"] + } + } + }, + "wanted_suspect": { + "default": { + "strong": [ + "wanted", + "most wanted", + "wanted suspect", + "fugitive", + "manhunt", + "public appeal" + ], + "negative": [ + "calendar", + "history", + "institution", + "policy", + "transparency", + "department" + ], + "url_hints": [ + "/wanted", + "/fugitive", + "/most-wanted" + ] + }, + "languages": { + "es": { + "strong": ["se busca", "buscado", "buscada", "profugo", "prófugo", "persona de interes policial"], + "negative": ["calendario", "historia", "institucion", "transparencia"], + "url_hints": ["/buscad", "/se-busca", "/interes-policial"] + }, + "ca": { + "strong": ["es busca", "buscat", "buscada", "fugitiu"], + "url_hints": ["/busca"] + }, + "fr": { + "strong": ["recherché", "recherche", "fugitif", "avis de recherche"], + "url_hints": ["/recherche", "/recherchee"] + }, + "de": { + "strong": ["gesucht", "fahndung", "flüchtig", "fluechtig"], + "url_hints": ["/gesucht", "/fahndung"] + }, + "it": { + "strong": ["ricercato", "ricercata", "latitante", "ricercati"], + "url_hints": ["/ricercat"] + }, + "pt": { + "strong": ["procurado", "procurada", "foragido", "suspeito procurado"], + "url_hints": ["/procurad", "/foragid"] + }, + "nl": { + "strong": ["gezocht", "voortvluchtig", "opgespoord"], + "url_hints": ["/gezocht"] + }, + "pl": { + "strong": ["poszukiwany", "poszukiwana", "zbieg"], + "url_hints": ["/poszukiw"] + }, + "ru": { + "strong": ["разыскивается", "в розыске", "беглец"], + "url_hints": ["/розыск", "/разыск"] + }, + "uk": { + "strong": ["розшукується", "у розшуку", "втікач"], + "url_hints": ["/розшук"] + }, + "ar": { + "strong": ["مطلوب", "هارب", "مشتبه به مطلوب"], + "url_hints": ["/مطلوب"] + }, + "tr": { + "strong": ["aranıyor", "aranan", "firari"], + "url_hints": ["/aran", "/firari"] + }, + "zh": { + "strong": ["通缉", "通緝", "在逃", "追缉", "追緝"], + "url_hints": ["/wanted", "/通缉", "/通緝"] + }, + "ja": { + "strong": ["指名手配", "逃走中", "公開手配"], + "url_hints": ["/wanted", "/指名手配"] + }, + "ko": { + "strong": ["지명수배", "수배", "도주범"], + "url_hints": ["/wanted", "/수배"] + }, + "hi": { + "strong": ["वांछित", "फरार", "मोस्ट वांटेड"], + "url_hints": ["/wanted"] + } + } + }, + "travel_warning": { + "default": { + "strong": ["travel warning", "do not travel", "reconsider travel", "advisory against travel"], + "url_hints": ["/travel", "/advisory"] + }, + "languages": { + "es": { "strong": ["aviso de viaje", "no viajar", "evite viajar"], "url_hints": ["/viaje"] }, + "fr": { "strong": ["conseil aux voyageurs", "ne pas voyager"], "url_hints": ["/voyage"] }, + "de": { "strong": ["reisewarnung", "nicht reisen"], "url_hints": ["/reise"] }, + "it": { "strong": ["avviso di viaggio", "non viaggiare"], "url_hints": ["/viaggio"] }, + "pt": { "strong": ["aviso de viagem", "nao viajar", "não viajar"], "url_hints": ["/viagem"] } + } + }, + "fraud_alert": { + "default": { + "strong": ["fraud alert", "scam alert", "phishing alert", "consumer warning"], + "url_hints": ["/fraud", "/scam", "/phishing"] + }, + "languages": { + "es": { "strong": ["alerta de fraude", "estafa", "phishing", "fraude"], "url_hints": ["/fraude", "/estafa"] }, + "fr": { "strong": ["alerte fraude", "escroquerie", "hameconnage"], "url_hints": ["/fraude", "/escroquerie"] }, + "de": { "strong": ["betrugswarnung", "phishing", "betrug"], "url_hints": ["/betrug", "/phishing"] }, + "pt": { "strong": ["alerta de fraude", "golpe", "phishing"], "url_hints": ["/fraude", "/golpe"] } + } + }, + "cyber_advisory": { + "default": { + "strong": ["security advisory", "vulnerability", "cve-", "patch", "exploit", "security bulletin"], + "url_hints": ["/advisory", "/alert", "/bulletin"] + }, + "languages": { + "es": { "strong": ["aviso de seguridad", "vulnerabilidad", "boletin de seguridad", "boletín de seguridad"] }, + "fr": { "strong": ["avis de securite", "avis de sécurité", "vulnerabilite", "vulnérabilité"] }, + "de": { "strong": ["sicherheitswarnung", "sicherheitsmeldung", "schwachstelle"] }, + "pt": { "strong": ["aviso de seguranca", "aviso de segurança", "vulnerabilidade"] } + } + }, + "public_appeal": { + "default": { + "strong": ["public appeal", "seeking information", "help identify", "report information"], + "url_hints": ["/appeal", "/seeking-information"] + }, + "languages": { + "es": { "strong": ["solicita informacion", "solicita información", "ayude a identificar", "informacion a la ciudadania"], "url_hints": ["/informacion"] }, + "fr": { "strong": ["appel a temoins", "appel à témoins", "recherche de renseignements"], "url_hints": ["/appel"] }, + "de": { "strong": ["zeugenaufruf", "hinweise erbeten", "hinweis gesucht"], "url_hints": ["/zeugen"] } + } + } + } +} diff --git a/registry/curated_agencies.seed.json b/registry/curated_agencies.seed.json new file mode 100644 index 0000000..8e57b4f --- /dev/null +++ b/registry/curated_agencies.seed.json @@ -0,0 +1,331 @@ +[ + { + "type": "rss", + "source": { + "source_id": "interpol-notices", + "authority_name": "INTERPOL Notices", + "country": "France", + "country_code": "FR", + "region": "International", + "authority_type": "police", + "base_url": "https://www.interpol.int", + "scope": "international", + "is_curated": true, + "is_high_value": true, + "language_code": "en" + }, + "feed_url": "https://www.interpol.int/How-we-work/Notices/View-Red-Notices", + "category": "wanted_suspect", + "region_tag": "INT", + "lat": 45.764, + "lng": 4.8357, + "reporting": { + "label": "Browse INTERPOL Notices", + "url": "https://www.interpol.int/How-we-work/Notices/View-Red-Notices" + } + }, + { + "type": "rss", + "source": { + "source_id": "interpol-missing", + "authority_name": "INTERPOL Missing Persons", + "country": "France", + "country_code": "FR", + "region": "International", + "authority_type": "police", + "base_url": "https://www.interpol.int", + "scope": "international", + "parent_agency_id": "interpol-notices", + "jurisdiction_name": "INTERPOL Missing Persons", + "is_curated": true, + "is_high_value": true, + "language_code": "en" + }, + "feed_url": "https://www.interpol.int/How-we-work/Notices/View-Yellow-Notices", + "category": "missing_person", + "region_tag": "INT", + "lat": 45.764, + "lng": 4.8357, + "reporting": { + "label": "Browse INTERPOL Yellow Notices", + "url": "https://www.interpol.int/How-we-work/Notices/View-Yellow-Notices" + } + }, + { + "type": "rss", + "source": { + "source_id": "europol", + "authority_name": "Europol", + "country": "Netherlands", + "country_code": "NL", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.europol.europa.eu", + "scope": "supranational", + "is_curated": true, + "is_high_value": true, + "language_code": "en" + }, + "feed_url": "https://www.europol.europa.eu/rss.xml", + "category": "public_appeal", + "region_tag": "EU", + "lat": 52.09, + "lng": 4.27, + "reporting": { + "label": "Report to Europol", + "url": "https://www.europol.europa.eu/report-a-crime" + } + }, + { + "type": "rss", + "source": { + "source_id": "fbi-wanted", + "authority_name": "FBI Wanted", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "police", + "base_url": "https://www.fbi.gov", + "scope": "national", + "is_curated": true, + "is_high_value": true, + "language_code": "en" + }, + "feed_url": "https://www.fbi.gov/wanted", + "category": "wanted_suspect", + "region_tag": "US", + "lat": 38.9, + "lng": -77.0, + "reporting": { + "label": "Submit a Tip to FBI", + "url": "https://tips.fbi.gov/" + } + }, + { + "type": "rss", + "source": { + "source_id": "fbi-seeking-info", + "authority_name": "FBI Seeking Information", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "police", + "base_url": "https://www.fbi.gov", + "scope": "national", + "parent_agency_id": "fbi-wanted", + "jurisdiction_name": "FBI Public Appeals", + "is_curated": true, + "is_high_value": true, + "language_code": "en" + }, + "feed_url": "https://www.fbi.gov/wanted/seeking-information", + "category": "public_appeal", + "region_tag": "US", + "lat": 38.9, + "lng": -77.0, + "reporting": { + "label": "Submit a Tip to FBI", + "url": "https://tips.fbi.gov/" + } + }, + { + "type": "rss", + "source": { + "source_id": "dea", + "authority_name": "Drug Enforcement Administration", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "police", + "base_url": "https://www.dea.gov", + "scope": "national", + "is_curated": true, + "is_high_value": true, + "language_code": "en" + }, + "feed_url": "https://www.dea.gov/press-releases/rss.xml", + "category": "public_safety", + "region_tag": "US", + "lat": 38.9072, + "lng": -77.0369, + "reporting": { + "label": "Report to DEA", + "url": "https://www.dea.gov/submit-tip" + } + }, + { + "type": "rss", + "source": { + "source_id": "doj", + "authority_name": "U.S. Department of Justice", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "regulatory", + "base_url": "https://www.justice.gov", + "scope": "national", + "is_curated": true, + "is_high_value": true, + "language_code": "en" + }, + "feed_url": "https://www.justice.gov/feeds/justice-news.xml", + "category": "public_safety", + "region_tag": "US", + "lat": 38.8951, + "lng": -77.0364, + "reporting": { + "label": "Contact DOJ", + "url": "https://www.justice.gov/doj/webform/your-message-department-justice" + } + }, + { + "type": "kev-json", + "source": { + "source_id": "cisa-kev", + "authority_name": "CISA", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "cert", + "base_url": "https://www.cisa.gov", + "scope": "national", + "is_curated": true, + "is_high_value": true, + "language_code": "en" + }, + "feed_url": "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json", + "category": "cyber_advisory", + "region_tag": "US", + "lat": 38.88, + "lng": -77.02, + "reporting": { + "label": "Report to CISA", + "url": "https://www.cisa.gov/report" + } + }, + { + "type": "rss", + "source": { + "source_id": "ncmec", + "authority_name": "National Center for Missing & Exploited Children", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "public_safety_program", + "base_url": "https://www.missingkids.org", + "scope": "national", + "is_curated": true, + "is_high_value": true, + "language_code": "en" + }, + "feed_url": "https://api.missingkids.org/missingkids/servlet/XmlServlet?LanguageCountry=en_US&act=rss&orgPrefix=NCMC", + "category": "missing_person", + "region_tag": "US", + "lat": 39.83, + "lng": -98.58, + "reporting": { + "label": "Report to NCMEC", + "url": "https://report.cybertip.org/" + } + }, + { + "type": "rss", + "source": { + "source_id": "bka", + "authority_name": "Bundeskriminalamt", + "country": "Germany", + "country_code": "DE", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.bka.de", + "scope": "national", + "is_curated": true, + "is_high_value": true, + "language_code": "de" + }, + "feed_url": "https://www.bka.de/SiteGlobals/Functions/RSSFeed/RSSGenerator.xml", + "category": "wanted_suspect", + "region_tag": "DE", + "lat": 50.1109, + "lng": 8.6821, + "reporting": { + "label": "Contact BKA", + "url": "https://www.bka.de" + } + }, + { + "type": "rss", + "source": { + "source_id": "bnd", + "authority_name": "Federal Intelligence Service (BND)", + "country": "Germany", + "country_code": "DE", + "region": "Europe", + "authority_type": "intelligence", + "base_url": "https://www.bnd.bund.de", + "scope": "national", + "is_curated": true, + "is_high_value": true, + "language_code": "de" + }, + "feed_url": "https://www.bnd.bund.de/EN/_rssfeed/rss_node.html", + "category": "public_safety", + "region_tag": "DE", + "lat": 52.52, + "lng": 13.405, + "reporting": { + "label": "Contact BND", + "url": "https://www.bnd.bund.de" + } + }, + { + "type": "rss", + "source": { + "source_id": "nca-uk", + "authority_name": "National Crime Agency", + "country": "United Kingdom", + "country_code": "GB", + "region": "Europe", + "authority_type": "police", + "base_url": "https://nationalcrimeagency.gov.uk", + "scope": "national", + "is_curated": true, + "is_high_value": true, + "language_code": "en" + }, + "feed_url": "https://nationalcrimeagency.gov.uk/news?format=feed&type=rss", + "category": "public_safety", + "region_tag": "GB", + "lat": 51.5074, + "lng": -0.1278, + "reporting": { + "label": "Report to NCA", + "url": "https://www.nationalcrimeagency.gov.uk/contact-us" + } + }, + { + "type": "rss", + "source": { + "source_id": "ncsc-uk", + "authority_name": "NCSC UK", + "country": "United Kingdom", + "country_code": "GB", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.ncsc.gov.uk", + "scope": "national", + "is_curated": true, + "is_high_value": true, + "language_code": "en" + }, + "feed_url": "https://www.ncsc.gov.uk/api/1/services/v1/all-rss-feed.xml", + "category": "cyber_advisory", + "region_tag": "GB", + "lat": 51.5, + "lng": -0.13, + "reporting": { + "label": "Report to NCSC", + "url": "https://www.ncsc.gov.uk/section/about-this-website/report-scam-website" + } + } +] diff --git a/registry/source_candidates.json b/registry/source_candidates.json new file mode 100644 index 0000000..2eaaa74 --- /dev/null +++ b/registry/source_candidates.json @@ -0,0 +1,4 @@ +{ + "generated_at": "", + "sources": [] +} diff --git a/registry/source_registry.json b/registry/source_registry.json index c5dc9a9..fb7066c 100644 --- a/registry/source_registry.json +++ b/registry/source_registry.json @@ -32,7 +32,7 @@ "authority_type": "police", "base_url": "https://www.fbi.gov" }, - "feed_url": "https://www.fbi.gov/feeds/fbi-top-stories/rss.xml", + "feed_url": "https://www.fbi.gov/wanted/seeking-information", "category": "public_appeal", "region_tag": "US", "lat": 38.9, @@ -55,7 +55,7 @@ "authority_type": "police", "base_url": "https://www.fbi.gov" }, - "feed_url": "https://www.fbi.gov/feeds/all-wanted/rss.xml", + "feed_url": "https://www.fbi.gov/wanted", "category": "wanted_suspect", "region_tag": "US", "lat": 38.9, @@ -358,7 +358,8 @@ } }, { - "type": "rss", + "type": "html-list", + "fetch_mode": "browser", "followRedirects": true, "source": { "source_id": "dhs", @@ -369,7 +370,7 @@ "authority_type": "national_security", "base_url": "https://www.dhs.gov" }, - "feed_url": "https://www.dhs.gov/news/rss.xml", + "feed_url": "https://www.dhs.gov/news-releases/press-releases", "category": "public_safety", "region_tag": "US", "lat": 38.886, @@ -378,7 +379,25 @@ "label": "Report to DHS", "url": "https://www.dhs.gov/see-something-say-something/how-to-report-suspicious-activity", "phone": "1-866-347-2423" - } + }, + "feed_urls": [ + "https://www.dhs.gov/news-releases/press-releases", + "https://www.dhs.gov/news" + ], + "max_items": 80, + "include_keywords": [ + "cyber", + "terror", + "security", + "incident", + "threat", + "seizure" + ], + "exclude_keywords": [ + "subscribe", + "blog", + "speeches" + ] }, { "type": "rss", @@ -404,7 +423,7 @@ } }, { - "type": "rss", + "type": "html-list", "followRedirects": true, "source": { "source_id": "dea", @@ -415,7 +434,7 @@ "authority_type": "police", "base_url": "https://www.dea.gov" }, - "feed_url": "https://www.dea.gov/press-releases/rss.xml", + "feed_url": "https://www.dea.gov/what-we-do/news/press-releases", "category": "public_appeal", "region_tag": "US", "lat": 38.871, @@ -424,10 +443,26 @@ "label": "Report to DEA", "url": "https://www.dea.gov/submit-tip", "phone": "1-877-792-2873" - } + }, + "feed_urls": [ + "https://www.dea.gov/what-we-do/news/press-releases" + ], + "max_items": 80, + "include_keywords": [ + "arrest", + "fentanyl", + "drug", + "traffick", + "seiz", + "operation" + ], + "exclude_keywords": [ + "submit a tip", + "subscribe" + ] }, { - "type": "rss", + "type": "html-list", "followRedirects": true, "source": { "source_id": "atf", @@ -438,7 +473,7 @@ "authority_type": "police", "base_url": "https://www.atf.gov" }, - "feed_url": "https://www.atf.gov/news/rss.xml", + "feed_url": "https://www.atf.gov/news/press-releases", "category": "public_appeal", "region_tag": "US", "lat": 38.893, @@ -448,7 +483,22 @@ "url": "https://www.atf.gov/contact/atf-tips", "phone": "1-888-283-8477", "email": "atftips@atf.gov" - } + }, + "feed_urls": [ + "https://www.atf.gov/news/press-releases" + ], + "max_items": 80, + "include_keywords": [ + "sentenced", + "arrest", + "firearm", + "explosive", + "gang", + "trafficking" + ], + "exclude_keywords": [ + "subscribe for atf updates" + ] }, { "type": "rss", @@ -520,53 +570,7 @@ } }, { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "met-police-uk", - "authority_name": "Met Police UK", - "country": "United Kingdom", - "country_code": "GB", - "region": "Europe", - "authority_type": "police", - "base_url": "https://news.met.police.uk" - }, - "feed_url": "https://news.met.police.uk/feeds/rss", - "category": "public_appeal", - "region_tag": "GB", - "lat": 51.51, - "lng": -0.14, - "reporting": { - "label": "Report to Met Police", - "url": "https://www.met.police.uk/ro/report/", - "phone": "999 (Emergency) / 101 (Non-emergency)" - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "bsi-de", - "authority_name": "BSI Germany", - "country": "Germany", - "country_code": "DE", - "region": "Europe", - "authority_type": "cert", - "base_url": "https://www.bsi.bund.de" - }, - "feed_url": "https://www.bsi.bund.de/SiteGlobals/Functions/RSSFeed/RSSNewsfeed/RSSNewsfeed.xml", - "category": "cyber_advisory", - "region_tag": "DE", - "lat": 50.73, - "lng": 7.1, - "reporting": { - "label": "Report to BSI", - "url": "https://www.bsi.bund.de/EN/Service-Navi/Contact/contact_node.html", - "email": "certbund@bsi.bund.de" - } - }, - { - "type": "rss", + "type": "html-list", "followRedirects": true, "source": { "source_id": "bka-de", @@ -577,7 +581,7 @@ "authority_type": "police", "base_url": "https://www.bka.de" }, - "feed_url": "https://www.bka.de/SharedDocs/Kurzmeldungen/DE/Warnhinweise/RSS/BKA_Pressemitteilungen_RSS.xml", + "feed_url": "https://www.bka.de/DE/Presse/Pressestelle/pressestelle_node.html", "category": "wanted_suspect", "region_tag": "DE", "lat": 50.12, @@ -586,7 +590,23 @@ "label": "Report to BKA", "url": "https://www.bka.de/DE/KontaktAufnehmen/Hinweisportal/hinweisportal_node.html", "phone": "+49 611 55-0" - } + }, + "feed_urls": [ + "https://www.bka.de/DE/Presse/Pressestelle/pressestelle_node.html" + ], + "max_items": 80, + "include_keywords": [ + "pressemitteilung", + "cyber", + "fahnd", + "kriminal", + "hasspost", + "festnahme" + ], + "exclude_keywords": [ + "kontakt", + "pressestelle" + ] }, { "type": "rss", @@ -616,34 +636,6 @@ "phone": "1300 292 371" } }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "afp-au", - "authority_name": "AFP Australia", - "country": "Australia", - "country_code": "AU", - "region": "Oceania", - "authority_type": "police", - "base_url": "https://www.afp.gov.au" - }, - "feed_url": "https://www.afp.gov.au/news-centre/media-releases/rss.xml", - "feed_urls": [ - "https://www.afp.gov.au/news-centre/media-releases/rss.xml", - "https://www.afp.gov.au/news-centre/media-release/rss.xml", - "https://www.afp.gov.au/news-centre/media-releases/feed" - ], - "category": "public_appeal", - "region_tag": "AU", - "lat": -35.31, - "lng": 149.14, - "reporting": { - "label": "Report to AFP", - "url": "https://www.afp.gov.au/what-we-do/crime-types/report-crime", - "phone": "131 237" - } - }, { "type": "rss", "followRedirects": true, @@ -673,35 +665,7 @@ } }, { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "nsw-police-au", - "authority_name": "NSW Police", - "country": "Australia", - "country_code": "AU", - "region": "Oceania", - "authority_type": "police", - "base_url": "https://www.police.nsw.gov.au" - }, - "feed_url": "https://www.police.nsw.gov.au/news/rss", - "feed_urls": [ - "https://www.police.nsw.gov.au/news/rss", - "https://www.police.nsw.gov.au/rss/news", - "https://www.police.nsw.gov.au/news/feed" - ], - "category": "public_appeal", - "region_tag": "AU", - "lat": -33.87, - "lng": 151.21, - "reporting": { - "label": "Report to NSW Police", - "url": "https://portal.police.nsw.gov.au/s/online-services", - "phone": "000 (Emergency) / 131 444 (Police Assistance Line)" - } - }, - { - "type": "rss", + "type": "html-list", "followRedirects": true, "source": { "source_id": "cccs-ca", @@ -712,7 +676,7 @@ "authority_type": "cert", "base_url": "https://www.cyber.gc.ca" }, - "feed_url": "https://www.cyber.gc.ca/en/alerts-advisories/feed", + "feed_url": "https://www.cyber.gc.ca/en/alerts-advisories", "category": "cyber_advisory", "region_tag": "CA", "lat": 45.42, @@ -722,7 +686,22 @@ "url": "https://www.cyber.gc.ca/en/incident-management", "email": "contact@cyber.gc.ca", "phone": "1-833-292-3722" - } + }, + "feed_urls": [ + "https://www.cyber.gc.ca/en/alerts-advisories" + ], + "max_items": 80, + "include_keywords": [ + "alert", + "advisory", + "vulnerability", + "cyber", + "threat" + ], + "exclude_keywords": [ + "contact", + "report a cyber incident" + ] }, { "type": "rss", @@ -748,7 +727,7 @@ } }, { - "type": "rss", + "type": "html-list", "followRedirects": true, "source": { "source_id": "cnp-es", @@ -759,7 +738,7 @@ "authority_type": "police", "base_url": "https://www.policia.es" }, - "feed_url": "https://www.policia.es/rss/rss_prensa.xml", + "feed_url": "https://www.policia.es/_es/comunicacion_salaprensa.php", "category": "public_appeal", "region_tag": "ES", "lat": 40.42, @@ -768,7 +747,25 @@ "label": "Report to Policía Nacional", "url": "https://www.policia.es/colabora.php", "phone": "091" - } + }, + "feed_urls": [ + "https://www.policia.es/_es/comunicacion_salaprensa.php", + "https://www.policia.es/_es/comunicacion_portada.php" + ], + "max_items": 80, + "include_keywords": [ + "prensa", + "detiene", + "operación", + "ciberdelincuencia", + "incauta", + "investigación" + ], + "exclude_keywords": [ + "síguenos", + "gabinete de prensa", + "cargar más" + ] }, { "type": "rss", @@ -898,35 +895,6 @@ "phone": "10111 (Emergency) / 08600 10111 (Crime Stop)" } }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "missing-children-za", - "authority_name": "Missing Children South Africa", - "country": "South Africa", - "country_code": "ZA", - "region": "Africa", - "authority_type": "public_safety_program", - "base_url": "https://missingchildren.org.za" - }, - "feed_url": "https://missingchildren.org.za/feed/", - "feed_urls": [ - "https://missingchildren.org.za/feed/", - "https://missingchildren.org.za/category/missing-children/feed/", - "https://missingchildren.org.za/category/cases/feed/" - ], - "category": "missing_person", - "region_tag": "ZA", - "lat": -29, - "lng": 24, - "reporting": { - "label": "Report to Missing Children SA", - "url": "https://missingchildren.org.za/report/", - "phone": "+27 72 647 7464", - "notes": "Coordinate directly with SAPS in emergency situations." - } - }, { "type": "rss", "followRedirects": true, @@ -951,52 +919,6 @@ "notes": "100% anonymous. You can also report online." } }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "npa-jp", - "authority_name": "Japan NPA", - "country": "Japan", - "country_code": "JP", - "region": "Asia", - "authority_type": "police", - "base_url": "https://www.npa.go.jp" - }, - "feed_url": "https://www.npa.go.jp/rss/index.xml", - "category": "public_safety", - "region_tag": "JP", - "lat": 35.69, - "lng": 139.75, - "reporting": { - "label": "Report to NPA Japan", - "url": "https://www.npa.go.jp/english/index.html", - "phone": "110 (Emergency)" - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "gendarmerie-fr", - "authority_name": "Gendarmerie France", - "country": "France", - "country_code": "FR", - "region": "Europe", - "authority_type": "police", - "base_url": "https://www.gendarmerie.interieur.gouv.fr" - }, - "feed_url": "https://www.gendarmerie.interieur.gouv.fr/rss", - "category": "public_appeal", - "region_tag": "FR", - "lat": 48.85, - "lng": 2.3, - "reporting": { - "label": "Report to Gendarmerie", - "url": "https://www.pre-plainte-en-ligne.gouv.fr/", - "phone": "17 (Emergency)" - } - }, { "type": "rss", "followRedirects": true, @@ -1071,34 +993,6 @@ "phone": "190 (Emergency)" } }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "carabineros-cl", - "authority_name": "Carabineros Chile", - "country": "Chile", - "country_code": "CL", - "region": "South America", - "authority_type": "police", - "base_url": "https://www.carabineros.cl" - }, - "feed_url": "https://www.carabineros.cl/feed/", - "feed_urls": [ - "https://www.carabineros.cl/feed/", - "https://www.carabineros.cl/rss", - "https://www.carabineros.cl/index.php/feed/" - ], - "category": "public_appeal", - "region_tag": "CL", - "lat": -33.45, - "lng": -70.67, - "reporting": { - "label": "Report to Carabineros", - "url": "https://www.carabineros.cl/", - "phone": "133 (Emergency)" - } - }, { "type": "rss", "followRedirects": true, @@ -1239,34 +1133,6 @@ "phone": "134 (PDI Emergency)" } }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "fiscales-ar", - "authority_name": "Ministerio Público Fiscal Argentina", - "country": "Argentina", - "country_code": "AR", - "region": "South America", - "authority_type": "regulatory", - "base_url": "https://www.fiscales.gob.ar" - }, - "feed_url": "https://www.fiscales.gob.ar/feed/", - "feed_urls": [ - "https://www.fiscales.gob.ar/feed/", - "https://www.fiscales.gob.ar/category/noticias/feed/", - "https://www.fiscales.gob.ar/category/cibercrimen/feed/" - ], - "category": "public_safety", - "region_tag": "AR", - "lat": -34.61, - "lng": -58.38, - "reporting": { - "label": "Report to Fiscalía Argentina", - "url": "https://www.mpf.gob.ar/", - "phone": "137 (Emergency advisory line)" - } - }, { "type": "rss", "followRedirects": true, @@ -1306,7 +1172,7 @@ "authority_type": "police", "base_url": "https://www.fbi.gov" }, - "feed_url": "https://www.fbi.gov/feeds/seeking-information/rss.xml", + "feed_url": "https://www.fbi.gov/wanted/seeking-information", "category": "public_appeal", "region_tag": "US", "lat": 38.91, @@ -1330,7 +1196,7 @@ "authority_type": "police", "base_url": "https://www.fbi.gov" }, - "feed_url": "https://www.fbi.gov/feeds/fbi-most-wanted/rss.xml", + "feed_url": "https://www.fbi.gov/wanted", "category": "wanted_suspect", "region_tag": "US", "lat": 38.89, @@ -1367,154 +1233,43 @@ }, { "type": "rss", + "followRedirects": true, "source": { - "source_id": "cna-sg-crime", - "authority_name": "CNA Singapore Crime", - "country": "Singapore", - "country_code": "SG", + "source_id": "pnp-ph", + "authority_name": "PNP Philippines", + "country": "Philippines", + "country_code": "PH", "region": "Asia", - "authority_type": "public_safety_program", - "base_url": "https://www.channelnewsasia.com" + "authority_type": "police", + "base_url": "https://www.pnp.gov.ph" }, - "feed_url": "https://www.channelnewsasia.com/api/v1/rss-outbound-feed?_format=xml&category=6511", - "category": "public_safety", - "region_tag": "SG", - "lat": 1.35, - "lng": 103.82, + "feed_url": "https://www.pnp.gov.ph/rss", + "feed_urls": [ + "https://www.pnp.gov.ph/rss", + "https://www.pnp.gov.ph/feed/", + "https://www.pnp.gov.ph/category/press-release/feed/" + ], + "category": "public_appeal", + "region_tag": "PH", + "lat": 14.6, + "lng": 120.98, "reporting": { - "label": "Report Crime in Singapore", - "url": "https://eservices.police.gov.sg/content/policehubhome/homepage/police-report.html", - "phone": "999 (Emergency) / 1800-255-0000 (Police Hotline)" + "label": "Report to PNP", + "url": "https://www.pnp.gov.ph/", + "phone": "117 (Emergency) / 8722-0650" } }, { "type": "rss", + "followRedirects": true, "source": { - "source_id": "yonhap-kr", - "authority_name": "Yonhap News Korea", - "country": "South Korea", - "country_code": "KR", + "source_id": "pdrm-my", + "authority_name": "PDRM Malaysia", + "country": "Malaysia", + "country_code": "MY", "region": "Asia", - "authority_type": "public_safety_program", - "base_url": "https://en.yna.co.kr" - }, - "feed_url": "https://en.yna.co.kr/RSS/news.xml", - "category": "public_safety", - "region_tag": "KR", - "lat": 37.57, - "lng": 126.98, - "reporting": { - "label": "Report Crime in South Korea", - "url": "https://www.police.go.kr/eng/index.do", - "phone": "112 (Emergency)" - } - }, - { - "type": "rss", - "source": { - "source_id": "nhk-jp", - "authority_name": "NHK Japan", - "country": "Japan", - "country_code": "JP", - "region": "Asia", - "authority_type": "public_safety_program", - "base_url": "https://www3.nhk.or.jp" - }, - "feed_url": "https://www3.nhk.or.jp/rss/news/cat1.xml", - "category": "public_safety", - "region_tag": "JP", - "lat": 35.67, - "lng": 139.71, - "reporting": { - "label": "Report to Japan Police", - "url": "https://www.npa.go.jp/english/index.html", - "phone": "110 (Emergency)" - } - }, - { - "type": "rss", - "source": { - "source_id": "scmp-hk", - "authority_name": "SCMP Hong Kong", - "country": "Hong Kong", - "country_code": "HK", - "region": "Asia", - "authority_type": "public_safety_program", - "base_url": "https://www.scmp.com" - }, - "feed_url": "https://www.scmp.com/rss/5/feed", - "followRedirects": true, - "category": "public_safety", - "region_tag": "HK", - "lat": 22.28, - "lng": 114.16, - "reporting": { - "label": "Report Crime in Hong Kong", - "url": "https://www.police.gov.hk/ppp_en/contact_us.html", - "phone": "999 (Emergency)" - } - }, - { - "type": "rss", - "source": { - "source_id": "straitstimes-sg", - "authority_name": "Straits Times Singapore", - "country": "Singapore", - "country_code": "SG", - "region": "Asia", - "authority_type": "public_safety_program", - "base_url": "https://www.straitstimes.com" - }, - "feed_url": "https://www.straitstimes.com/news/singapore/rss.xml", - "category": "public_safety", - "region_tag": "SG", - "lat": 1.3, - "lng": 103.84, - "reporting": { - "label": "Report Crime in Singapore", - "url": "https://eservices.police.gov.sg/content/policehubhome/homepage/police-report.html", - "phone": "999 (Emergency)" - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "pnp-ph", - "authority_name": "PNP Philippines", - "country": "Philippines", - "country_code": "PH", - "region": "Asia", - "authority_type": "police", - "base_url": "https://www.pnp.gov.ph" - }, - "feed_url": "https://www.pnp.gov.ph/rss", - "feed_urls": [ - "https://www.pnp.gov.ph/rss", - "https://www.pnp.gov.ph/feed/", - "https://www.pnp.gov.ph/category/press-release/feed/" - ], - "category": "public_appeal", - "region_tag": "PH", - "lat": 14.6, - "lng": 120.98, - "reporting": { - "label": "Report to PNP", - "url": "https://www.pnp.gov.ph/", - "phone": "117 (Emergency) / 8722-0650" - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "pdrm-my", - "authority_name": "PDRM Malaysia", - "country": "Malaysia", - "country_code": "MY", - "region": "Asia", - "authority_type": "police", - "base_url": "https://www.pdrm.gov.my" + "authority_type": "police", + "base_url": "https://www.pdrm.gov.my" }, "feed_url": "https://www.pdrm.gov.my/rss", "feed_urls": [ @@ -1632,79 +1387,6 @@ "notes": "Denuncia anónima / Anonymous tip line." } }, - { - "type": "html-list", - "followRedirects": true, - "source": { - "source_id": "amber-mx", - "authority_name": "AMBER Alert Mexico", - "country": "Mexico", - "country_code": "MX", - "region": "North America", - "authority_type": "public_safety_program", - "base_url": "https://www.gob.mx/amber" - }, - "feed_url": "https://www.gob.mx/amber/archivo/acciones_y_programas", - "feed_urls": [ - "https://www.gob.mx/amber/archivo/acciones_y_programas", - "https://www.gob.mx/amber/es/archivo/acciones_y_programas", - "https://www.gob.mx/amber" - ], - "include_keywords": [ - "alerta amber", - "desaparec", - "no localizado", - "se busca", - "ficha", - "menor", - "niña", - "niño", - "adolescente", - "auxilio", - "información" - ], - "exclude_keywords": [ - "evento", - "campaña", - "conferencia", - "manual", - "material" - ], - "category": "missing_person", - "region_tag": "MX", - "lat": 19.44, - "lng": -99.14, - "reporting": { - "label": "Report Missing Child Mexico", - "url": "https://www.gob.mx/amber", - "phone": "800-008-5400", - "notes": "Alerta AMBER México" - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "missing-ca", - "authority_name": "Canada Missing Children", - "country": "Canada", - "country_code": "CA", - "region": "North America", - "authority_type": "public_safety_program", - "base_url": "https://www.canadasmissing.ca" - }, - "feed_url": "https://www.canadasmissing.ca/rss/index-eng.xml", - "category": "missing_person", - "region_tag": "CA", - "lat": 45.43, - "lng": -75.68, - "reporting": { - "label": "Report Missing Person Canada", - "url": "https://www.canadasmissing.ca/index-eng.htm", - "phone": "1-866-KID-TIPS (1-866-543-8477)", - "notes": "Canadian Centre for Child Protection" - } - }, { "type": "rss", "followRedirects": true, @@ -1809,98 +1491,6 @@ "notes": "Use official BSSN contact channels for incident reporting." } }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "bleepingcomputer", - "authority_name": "BleepingComputer", - "country": "United States", - "country_code": "US", - "region": "North America", - "authority_type": "private_sector", - "base_url": "https://www.bleepingcomputer.com" - }, - "feed_url": "https://www.bleepingcomputer.com/feed/", - "category": "private_sector", - "region_tag": "US", - "lat": 40.71, - "lng": -74.01, - "reporting": { - "label": "Read Full Report", - "url": "https://www.bleepingcomputer.com", - "notes": "Private-sector cybersecurity news. Report incidents to relevant authorities." - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "krebsonsecurity", - "authority_name": "Krebs on Security", - "country": "United States", - "country_code": "US", - "region": "North America", - "authority_type": "private_sector", - "base_url": "https://krebsonsecurity.com" - }, - "feed_url": "https://krebsonsecurity.com/feed/", - "category": "private_sector", - "region_tag": "US", - "lat": 38.9, - "lng": -77.04, - "reporting": { - "label": "Read Full Report", - "url": "https://krebsonsecurity.com", - "notes": "Investigative cybersecurity journalism by Brian Krebs." - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "thehackernews", - "authority_name": "The Hacker News", - "country": "United States", - "country_code": "US", - "region": "North America", - "authority_type": "private_sector", - "base_url": "https://thehackernews.com" - }, - "feed_url": "https://feeds.feedburner.com/TheHackersNews", - "category": "private_sector", - "region_tag": "US", - "lat": 37.39, - "lng": -122.08, - "reporting": { - "label": "Read Full Report", - "url": "https://thehackernews.com", - "notes": "Cybersecurity news and analysis." - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "databreaches-net", - "authority_name": "DataBreaches.net", - "country": "United States", - "country_code": "US", - "region": "North America", - "authority_type": "private_sector", - "base_url": "https://databreaches.net" - }, - "feed_url": "https://databreaches.net/feed/", - "category": "private_sector", - "region_tag": "US", - "lat": 39.83, - "lng": -98.58, - "reporting": { - "label": "Read Full Report", - "url": "https://databreaches.net", - "notes": "Data breach tracking and reporting." - } - }, { "type": "rss", "followRedirects": true, @@ -1972,50 +1562,6 @@ "phone": "1-833-CYBER-88" } }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "cbc-canada", - "authority_name": "CBC Canada News", - "country": "Canada", - "country_code": "CA", - "region": "North America", - "authority_type": "public_safety_program", - "base_url": "https://www.cbc.ca" - }, - "feed_url": "https://www.cbc.ca/webfeed/rss/rss-canada", - "category": "public_safety", - "region_tag": "CA", - "lat": 43.6532, - "lng": -79.3832, - "reporting": { - "label": "CBC News Tips", - "url": "https://www.cbc.ca/news/tips" - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "globalnews-ca", - "authority_name": "Global News Canada", - "country": "Canada", - "country_code": "CA", - "region": "North America", - "authority_type": "public_safety_program", - "base_url": "https://globalnews.ca" - }, - "feed_url": "https://globalnews.ca/feed/", - "category": "public_safety", - "region_tag": "CA", - "lat": 45.5017, - "lng": -73.5673, - "reporting": { - "label": "Global News Tips", - "url": "https://globalnews.ca/pages/contact-us/" - } - }, { "type": "rss", "followRedirects": true, @@ -2039,430 +1585,60 @@ } }, { - "type": "rss", + "type": "html-list", "followRedirects": true, "source": { - "source_id": "timesofisrael-il", - "authority_name": "Times of Israel", - "country": "Israel", - "country_code": "IL", - "region": "Asia", - "authority_type": "public_safety_program", - "base_url": "https://www.timesofisrael.com" + "source_id": "kenya-dci-wanted", + "authority_name": "Kenya DCI Wanted", + "country": "Kenya", + "country_code": "KE", + "region": "Africa", + "authority_type": "police", + "base_url": "https://www.dci.go.ke" }, - "feed_url": "https://www.timesofisrael.com/feed/", - "category": "public_safety", - "region_tag": "IL", - "lat": 31.7683, - "lng": 35.2137, + "feed_url": "https://www.dci.go.ke/wanted/", + "category": "wanted_suspect", + "region_tag": "KE", + "lat": -1.286389, + "lng": 36.817223, + "max_items": 80, + "include_keywords": [ + "wanted", + "suspect", + "fugitive", + "appeal", + "missing" + ], "reporting": { - "label": "Israel Police Tips", - "url": "https://www.police.gov.il/en", - "phone": "100 (Israel Police)" + "label": "Report to Kenya DCI", + "url": "https://www.dci.go.ke/contact-us/", + "phone": "+254 20 2710000" } }, { - "type": "rss", + "type": "html-list", "followRedirects": true, "source": { - "source_id": "middleeasteye", - "authority_name": "Middle East Eye", - "country": "Qatar", - "country_code": "QA", - "region": "Asia", - "authority_type": "public_safety_program", - "base_url": "https://www.middleeasteye.net" + "source_id": "osp-gh-wanted", + "authority_name": "Ghana OSP Wanted Cases", + "country": "Ghana", + "country_code": "GH", + "region": "Africa", + "authority_type": "regulatory", + "base_url": "https://osp.gov.gh" }, - "feed_url": "https://www.middleeasteye.net/rss", - "category": "public_safety", - "region_tag": "ME", - "lat": 25.2854, - "lng": 51.531, - "reporting": { - "label": "Middle East Eye Tips", - "url": "https://www.middleeasteye.net/contact" - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "dailysabah-tr", - "authority_name": "Daily Sabah Turkey", - "country": "Turkey", - "country_code": "TR", - "region": "Asia", - "authority_type": "public_safety_program", - "base_url": "https://www.dailysabah.com" - }, - "feed_url": "https://www.dailysabah.com/rssFeed/turkey", - "category": "public_safety", - "region_tag": "TR", - "lat": 41.0082, - "lng": 28.9784, - "reporting": { - "label": "Daily Sabah Contact", - "url": "https://www.dailysabah.com/contact" - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "globaltimes-cn", - "authority_name": "Global Times China", - "country": "China", - "country_code": "CN", - "region": "Asia", - "authority_type": "public_safety_program", - "base_url": "https://www.globaltimes.cn" - }, - "feed_url": "https://www.globaltimes.cn/rss/outbrain.xml", - "category": "public_safety", - "region_tag": "CN", - "lat": 39.9042, - "lng": 116.4074, - "reporting": { - "label": "Global Times Contact", - "url": "https://www.globaltimes.cn/about-us/contact-us.html" - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "indiatoday-crime", - "authority_name": "India Today Crime", - "country": "India", - "country_code": "IN", - "region": "Asia", - "authority_type": "public_safety_program", - "base_url": "https://www.indiatoday.in" - }, - "feed_url": "https://www.indiatoday.in/rss/1786661", - "category": "public_safety", - "region_tag": "IN", - "lat": 28.6139, - "lng": 77.209, - "reporting": { - "label": "India Crime Tips", - "url": "https://cybercrime.gov.in/", - "phone": "112 (India Emergency)" - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "ndtv-in", - "authority_name": "NDTV India News", - "country": "India", - "country_code": "IN", - "region": "Asia", - "authority_type": "public_safety_program", - "base_url": "https://www.ndtv.com" - }, - "feed_url": "https://feeds.feedburner.com/ndtvnews-india-news", - "category": "public_safety", - "region_tag": "IN", - "lat": 19.076, - "lng": 72.8777, - "reporting": { - "label": "NDTV News Tips", - "url": "https://www.ndtv.com/page/contact-us", - "phone": "112 (India Emergency)" - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "hindustantimes-in", - "authority_name": "Hindustan Times India", - "country": "India", - "country_code": "IN", - "region": "Asia", - "authority_type": "public_safety_program", - "base_url": "https://www.hindustantimes.com" - }, - "feed_url": "https://www.hindustantimes.com/feeds/rss/india-news/rssfeed.xml", - "category": "public_safety", - "region_tag": "IN", - "lat": 12.9716, - "lng": 77.5946, - "reporting": { - "label": "Hindustan Times Tips", - "url": "https://www.hindustantimes.com/contact-us", - "phone": "112 (India Emergency)" - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "vnexpress-vn", - "authority_name": "VnExpress International", - "country": "Vietnam", - "country_code": "VN", - "region": "Asia", - "authority_type": "public_safety_program", - "base_url": "https://e.vnexpress.net" - }, - "feed_url": "https://e.vnexpress.net/rss/news.rss", - "category": "public_safety", - "region_tag": "VN", - "lat": 21.0278, - "lng": 105.8342, - "reporting": { - "label": "Vietnam Police Tips", - "url": "https://congan.com.vn/", - "phone": "113 (Vietnam Police)" - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "laotiantimes-la", - "authority_name": "Laotian Times", - "country": "Laos", - "country_code": "LA", - "region": "Asia", - "authority_type": "public_safety_program", - "base_url": "https://laotiantimes.com" - }, - "feed_url": "https://laotiantimes.com/feed/", - "category": "public_safety", - "region_tag": "LA", - "lat": 17.9757, - "lng": 102.6331, - "reporting": { - "label": "Laotian Times Contact", - "url": "https://laotiantimes.com/contact/" - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "bangkokpost-th", - "authority_name": "Bangkok Post", - "country": "Thailand", - "country_code": "TH", - "region": "Asia", - "authority_type": "public_safety_program", - "base_url": "https://www.bangkokpost.com" - }, - "feed_url": "https://www.bangkokpost.com/rss/data/topstories.xml", - "category": "public_safety", - "region_tag": "TH", - "lat": 13.7563, - "lng": 100.5018, - "reporting": { - "label": "Thailand Police Tips", - "url": "https://www.royalthaipolice.go.th/", - "phone": "191 (Thailand Police)" - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "rappler-ph", - "authority_name": "Rappler Philippines", - "country": "Philippines", - "country_code": "PH", - "region": "Asia", - "authority_type": "public_safety_program", - "base_url": "https://www.rappler.com" - }, - "feed_url": "https://www.rappler.com/feed/", - "category": "public_safety", - "region_tag": "PH", - "lat": 14.5995, - "lng": 120.9842, - "reporting": { - "label": "PNP Philippines Tips", - "url": "https://www.pnp.gov.ph/", - "phone": "117 (PH Emergency)" - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "tempo-id", - "authority_name": "Tempo Indonesia", - "country": "Indonesia", - "country_code": "ID", - "region": "Asia", - "authority_type": "public_safety_program", - "base_url": "https://en.tempo.co" - }, - "feed_url": "https://rss.tempo.co/en/", - "category": "public_safety", - "region_tag": "ID", - "lat": -6.2088, - "lng": 106.8456, - "reporting": { - "label": "Indonesia Police Tips", - "url": "https://www.polri.go.id/", - "phone": "110 (Indonesia Police)" - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "postcourier-pg", - "authority_name": "Post-Courier PNG", - "country": "Papua New Guinea", - "country_code": "PG", - "region": "Oceania", - "authority_type": "public_safety_program", - "base_url": "https://www.postcourier.com.pg" - }, - "feed_url": "https://www.postcourier.com.pg/feed/", - "category": "public_safety", - "region_tag": "PG", - "lat": -6.3149, - "lng": 147.1802, - "reporting": { - "label": "PNG Police", - "url": "https://www.rpngc.gov.pg/", - "phone": "000 (PNG Emergency)" - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "fijitimes-fj", - "authority_name": "Fiji Times", - "country": "Fiji", - "country_code": "FJ", - "region": "Oceania", - "authority_type": "public_safety_program", - "base_url": "https://www.fijitimes.com" - }, - "feed_url": "https://www.fijitimes.com/feed/", - "category": "public_safety", - "region_tag": "FJ", - "lat": -18.1416, - "lng": 178.4419, - "reporting": { - "label": "Fiji Police", - "url": "https://www.police.gov.fj/", - "phone": "917 (Fiji Police)" - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "rnz-pacific", - "authority_name": "RNZ Pacific", - "country": "New Zealand", - "country_code": "NZ", - "region": "Oceania", - "authority_type": "public_safety_program", - "base_url": "https://www.rnz.co.nz" - }, - "feed_url": "https://www.rnz.co.nz/rss/pacific.xml", - "category": "public_safety", - "region_tag": "NZ", - "lat": -15.3767, - "lng": 166.9592, - "reporting": { - "label": "RNZ Pacific Contact", - "url": "https://www.rnz.co.nz/about/contact" - } - }, - { - "type": "html-list", - "followRedirects": true, - "source": { - "source_id": "kenya-dci-wanted", - "authority_name": "Kenya DCI Wanted", - "country": "Kenya", - "country_code": "KE", - "region": "Africa", - "authority_type": "police", - "base_url": "https://www.dci.go.ke" - }, - "feed_url": "https://www.dci.go.ke/wanted/", - "category": "wanted_suspect", - "region_tag": "KE", - "lat": -1.286389, - "lng": 36.817223, - "max_items": 80, - "include_keywords": [ - "wanted", - "suspect", - "fugitive", - "appeal", - "missing" - ], - "reporting": { - "label": "Report to Kenya DCI", - "url": "https://www.dci.go.ke/contact-us/", - "phone": "+254 20 2710000" - } - }, - { - "type": "html-list", - "followRedirects": true, - "source": { - "source_id": "eoco-gh-wanted", - "authority_name": "EOCO Ghana Wanted Persons", - "country": "Ghana", - "country_code": "GH", - "region": "Africa", - "authority_type": "police", - "base_url": "https://www.eoco.gov.gh" - }, - "feed_url": "https://www.eoco.gov.gh/wanted-persons/", - "category": "wanted_suspect", - "region_tag": "GH", - "lat": 5.603717, - "lng": -0.186964, - "max_items": 80, - "include_keywords": [ - "wanted", - "suspect", - "fraud", - "crime", - "appeal" - ], - "reporting": { - "label": "Report to EOCO Ghana", - "url": "https://www.eoco.gov.gh/contact-us/" - } - }, - { - "type": "html-list", - "followRedirects": true, - "source": { - "source_id": "osp-gh-wanted", - "authority_name": "Ghana OSP Wanted Cases", - "country": "Ghana", - "country_code": "GH", - "region": "Africa", - "authority_type": "regulatory", - "base_url": "https://osp.gov.gh" - }, - "feed_url": "https://osp.gov.gh/case_files/wanted/", - "category": "wanted_suspect", - "region_tag": "GH", - "lat": 5.603717, - "lng": -0.186964, - "max_items": 80, - "include_keywords": [ - "wanted", - "case", - "appeal", - "fugitive" - ], + "feed_url": "https://osp.gov.gh/case_files/wanted/", + "category": "wanted_suspect", + "region_tag": "GH", + "lat": 5.603717, + "lng": -0.186964, + "max_items": 80, + "include_keywords": [ + "wanted", + "case", + "appeal", + "fugitive" + ], "reporting": { "label": "Report to Ghana OSP", "url": "https://osp.gov.gh/contact/" @@ -2560,45 +1736,6 @@ "phone": "08600 10111" } }, - { - "type": "html-list", - "followRedirects": true, - "source": { - "source_id": "missingchildren-za-html", - "authority_name": "Missing Children South Africa Cases", - "country": "South Africa", - "country_code": "ZA", - "region": "Africa", - "authority_type": "public_safety_program", - "base_url": "https://missingchildren.org.za" - }, - "feed_url": "https://missingchildren.org.za/category/cases/", - "feed_urls": [ - "https://missingchildren.org.za/category/cases/", - "https://missingchildren.org.za/category/missing-children/" - ], - "category": "missing_person", - "region_tag": "ZA", - "lat": -29, - "lng": 24, - "max_items": 120, - "include_keywords": [ - "missing", - "child", - "teen", - "appeal", - "case" - ], - "exclude_keywords": [ - "donate", - "event", - "newsletter" - ], - "reporting": { - "label": "Report Missing Person to MCSA", - "url": "https://missingchildren.org.za/report/" - } - }, { "type": "rss", "followRedirects": true, @@ -2649,36 +1786,6 @@ "url": "https://cert-mu.govmu.org/Pages/incident-reporting.aspx" } }, - { - "type": "html-list", - "followRedirects": true, - "source": { - "source_id": "ngcert-ng-bulletins", - "authority_name": "ngCERT Nigeria Bulletins", - "country": "Nigeria", - "country_code": "NG", - "region": "Africa", - "authority_type": "cert", - "base_url": "https://www.cert.gov.ng" - }, - "feed_url": "https://www.cert.gov.ng/", - "category": "cyber_advisory", - "region_tag": "NG", - "lat": 9.082, - "lng": 8.6753, - "max_items": 100, - "include_keywords": [ - "advisory", - "alert", - "threat", - "vulnerability", - "incident" - ], - "reporting": { - "label": "Report Incident to ngCERT", - "url": "https://www.cert.gov.ng/" - } - }, { "type": "html-list", "followRedirects": true, @@ -2690,68 +1797,24 @@ "region": "Africa", "authority_type": "cert", "base_url": "https://www.cert.tn" - }, - "feed_url": "https://www.cert.tn/", - "category": "cyber_advisory", - "region_tag": "TN", - "lat": 33.886917, - "lng": 9.537499, - "max_items": 100, - "include_keywords": [ - "alerte", - "advisory", - "vuln", - "threat", - "incident", - "cyber" - ], - "reporting": { - "label": "Report Incident to CERT-TN", - "url": "https://www.cert.tn/" - } - }, - { - "type": "html-list", - "followRedirects": true, - "source": { - "source_id": "mp-gt-casos", - "authority_name": "Ministerio Publico Guatemala Casos", - "country": "Guatemala", - "country_code": "GT", - "region": "North America", - "authority_type": "regulatory", - "base_url": "https://www.mp.gob.gt" - }, - "feed_url": "https://www.mp.gob.gt/noticias/", - "feed_urls": [ - "https://www.mp.gob.gt/noticias/", - "https://www.mp.gob.gt/category/noticias/", - "https://www.mp.gob.gt" - ], - "category": "public_appeal", - "region_tag": "GT", - "lat": 14.634915, - "lng": -90.506882, - "max_items": 120, + }, + "feed_url": "https://www.cert.tn/", + "category": "cyber_advisory", + "region_tag": "TN", + "lat": 33.886917, + "lng": 9.537499, + "max_items": 100, "include_keywords": [ - "desaparec", - "secuestro", - "se busca", - "captura", - "investigacion", - "denuncia", - "fiscalia", - "homicidio" - ], - "exclude_keywords": [ - "evento", - "licitacion", - "boletin", - "agenda" + "alerte", + "advisory", + "vuln", + "threat", + "incident", + "cyber" ], "reporting": { - "label": "Report to MP Guatemala", - "url": "https://www.mp.gob.gt" + "label": "Report Incident to CERT-TN", + "url": "https://www.cert.tn/" } }, { @@ -3003,84 +2066,6 @@ "url": "https://acleddata.com/data-export-tool/" } }, - { - "type": "html-list", - "followRedirects": true, - "source": { - "source_id": "hot-tasking", - "authority_name": "Humanitarian OpenStreetMap Team", - "country": "Global", - "country_code": "INT", - "region": "International", - "authority_type": "public_safety_program", - "base_url": "https://www.hotosm.org" - }, - "feed_url": "https://www.hotosm.org/projects/", - "feed_urls": [ - "https://www.hotosm.org/projects/", - "https://tasks.hotosm.org/explore" - ], - "category": "humanitarian_tasking", - "region_tag": "INT", - "lat": 20, - "lng": 0, - "max_items": 100, - "include_keywords": [ - "mapping", - "task", - "response", - "disaster", - "humanitarian", - "project" - ], - "exclude_keywords": [ - "careers", - "donate" - ], - "reporting": { - "label": "Join HOT Mapping Tasks", - "url": "https://tasks.hotosm.org/" - } - }, - { - "type": "html-list", - "followRedirects": true, - "source": { - "source_id": "missing-maps-tasking", - "authority_name": "Missing Maps", - "country": "Global", - "country_code": "INT", - "region": "International", - "authority_type": "public_safety_program", - "base_url": "https://www.missingmaps.org" - }, - "feed_url": "https://www.missingmaps.org/", - "feed_urls": [ - "https://www.missingmaps.org/", - "https://www.missingmaps.org/blog/" - ], - "category": "humanitarian_tasking", - "region_tag": "INT", - "lat": 20, - "lng": 0, - "max_items": 80, - "include_keywords": [ - "mapathon", - "mapping", - "task", - "response", - "field", - "vulnerable" - ], - "exclude_keywords": [ - "donate", - "shop" - ], - "reporting": { - "label": "Join Missing Maps", - "url": "https://www.missingmaps.org/get-involved/" - } - }, { "type": "html-list", "followRedirects": true, @@ -3157,594 +2142,598 @@ } }, { - "type": "html-list", - "followRedirects": true, + "type": "rss", "source": { - "source_id": "ict4peace-briefings", - "authority_name": "ICT4Peace", - "country": "Global", - "country_code": "INT", - "region": "International", - "authority_type": "public_safety_program", - "base_url": "https://ict4peace.org" + "source_id": "bsi-certbund", + "authority_name": "CERT-Bund", + "country": "Germany", + "country_code": "DE", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.bsi.bund.de" }, - "feed_url": "https://ict4peace.org/", - "feed_urls": [ - "https://ict4peace.org/", - "https://ict4peace.org/category/publications/" - ], - "category": "humanitarian_tasking", - "region_tag": "INT", - "lat": 20, - "lng": 0, - "max_items": 80, - "include_keywords": [ - "crisis", - "humanitarian", - "technology", - "coordination", - "response" - ], - "exclude_keywords": [ - "about", - "board", - "contact" - ], + "feed_url": "https://wid.cert-bund.de/content/public/securityAdvisory/rss", + "category": "cyber_advisory", + "region_tag": "DE", + "lat": 50.73, + "lng": 7.1, + "reporting": { + "label": "Report to BSI", + "url": "https://www.bsi.bund.de/DE/IT-Sicherheitsvorfall/it-sicherheitsvorfall_node.html" + } + }, + { + "type": "rss", + "source": { + "source_id": "bsi-csw", + "authority_name": "BSI Cyber-Sicherheitswarnungen", + "country": "Germany", + "country_code": "DE", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.bsi.bund.de" + }, + "feed_url": "https://www.bsi.bund.de/SiteGlobals/Functions/RSSFeed/RSSNewsfeed/RSSNewsfeed_CSW.xml", + "category": "cyber_advisory", + "region_tag": "DE", + "lat": 50.73, + "lng": 7.09, + "reporting": { + "label": "Report to BSI", + "url": "https://www.bsi.bund.de/DE/IT-Sicherheitsvorfall/it-sicherheitsvorfall_node.html" + } + }, + { + "type": "rss", + "source": { + "source_id": "bsi-kritis", + "authority_name": "BSI KRITIS", + "country": "Germany", + "country_code": "DE", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.bsi.bund.de" + }, + "feed_url": "https://www.bsi.bund.de/SiteGlobals/Functions/RSSFeed/RSSNewsfeed/RSSNewsfeed_KRITIS-aktuell.xml", + "category": "cyber_advisory", + "region_tag": "DE", + "lat": 50.74, + "lng": 7.1, + "reporting": { + "label": "Report to BSI", + "url": "https://www.bsi.bund.de/DE/IT-Sicherheitsvorfall/it-sicherheitsvorfall_node.html" + } + }, + { + "type": "rss", + "source": { + "source_id": "bsi-nesas", + "authority_name": "BSI NESAS", + "country": "Germany", + "country_code": "DE", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.bsi.bund.de" + }, + "feed_url": "https://www.bsi.bund.de/SiteGlobals/Functions/RSSFeed/RSSNewsfeed/RSSNewsfeed_NESAS.xml", + "category": "cyber_advisory", + "region_tag": "DE", + "lat": 50.72, + "lng": 7.1, + "reporting": { + "label": "Report to BSI", + "url": "https://www.bsi.bund.de/DE/IT-Sicherheitsvorfall/it-sicherheitsvorfall_node.html" + } + }, + { + "type": "rss", + "source": { + "source_id": "bsi-buergercert", + "authority_name": "BSI Bürger-CERT", + "country": "Germany", + "country_code": "DE", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.bsi.bund.de" + }, + "feed_url": "https://wid.cert-bund.de/content/public/buergercert/rss", + "category": "cyber_advisory", + "region_tag": "DE", + "lat": 50.74, + "lng": 7.09, + "reporting": { + "label": "Report to BSI", + "url": "https://www.bsi.bund.de/DE/IT-Sicherheitsvorfall/it-sicherheitsvorfall_node.html" + } + }, + { + "type": "rss", + "source": { + "source_id": "sans-isc", + "authority_name": "SANS Internet Storm Center", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "cert", + "base_url": "https://isc.sans.edu" + }, + "feed_url": "https://isc.sans.edu/rssfeed.xml", + "category": "cyber_advisory", + "region_tag": "US", + "lat": 38.95, + "lng": -77.35, + "reporting": { + "label": "Report to SANS ISC", + "url": "https://isc.sans.edu/contact.html" + } + }, + { + "type": "rss", + "source": { + "source_id": "cert-at", + "authority_name": "CERT.at", + "country": "Austria", + "country_code": "AT", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://cert.at" + }, + "feed_url": "https://www.cert.at/cert-at.de.warnings.rss_2.0.xml", + "category": "cyber_advisory", + "region_tag": "AT", + "lat": 48.21, + "lng": 16.37, + "reporting": { + "label": "Report to CERT.at", + "url": "https://cert.at/de/melden" + } + }, + { + "type": "rss", + "source": { + "source_id": "ccn-cert-es", + "authority_name": "CCN-CERT Spain", + "country": "Spain", + "country_code": "ES", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.ccn-cert.cni.es" + }, + "feed_url": "https://www.ccn-cert.cni.es/es/seguridad-al-dia/alertas-ccn-cert.html?format=feed&type=rss", + "category": "cyber_advisory", + "region_tag": "ES", + "lat": 40.42, + "lng": -3.7, + "reporting": { + "label": "Report to CCN-CERT", + "url": "https://www.ccn-cert.cni.es/es/comunicacion-eventos/contacto.html" + } + }, + { + "type": "rss", + "source": { + "source_id": "cert-se", + "authority_name": "CERT-SE", + "country": "Sweden", + "country_code": "SE", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.cert.se" + }, + "feed_url": "https://www.cert.se/feed/", + "category": "cyber_advisory", + "region_tag": "SE", + "lat": 59.33, + "lng": 18.07, + "reporting": { + "label": "Report to CERT-SE", + "url": "https://www.cert.se/om-cert-se/rapportera-en-incident/" + } + }, + { + "type": "rss", + "source": { + "source_id": "cert-pl", + "authority_name": "CERT.PL", + "country": "Poland", + "country_code": "PL", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://cert.pl" + }, + "feed_url": "https://cert.pl/en/rss.xml", + "category": "cyber_advisory", + "region_tag": "PL", + "lat": 52.23, + "lng": 21.01, + "reporting": { + "label": "Report to CERT.PL", + "url": "https://incydent.cert.pl/" + } + }, + { + "type": "rss", + "source": { + "source_id": "cert-lv", + "authority_name": "CERT.LV", + "country": "Latvia", + "country_code": "LV", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.cert.lv" + }, + "feed_url": "https://www.cert.lv/en/rss/news.xml", + "category": "cyber_advisory", + "region_tag": "LV", + "lat": 56.95, + "lng": 24.11, + "reporting": { + "label": "Report to CERT.LV", + "url": "https://www.cert.lv/en/report" + } + }, + { + "type": "rss", + "source": { + "source_id": "cert-hr", + "authority_name": "CERT.hr", + "country": "Croatia", + "country_code": "HR", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.cert.hr" + }, + "feed_url": "https://www.cert.hr/feed/", + "category": "cyber_advisory", + "region_tag": "HR", + "lat": 45.81, + "lng": 15.98, + "reporting": { + "label": "Report to CERT.hr", + "url": "https://www.cert.hr/prijava-incidenta/" + } + }, + { + "type": "rss", + "source": { + "source_id": "si-cert", + "authority_name": "SI-CERT", + "country": "Slovenia", + "country_code": "SI", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.cert.si" + }, + "feed_url": "https://www.cert.si/en/feed/", + "category": "cyber_advisory", + "region_tag": "SI", + "lat": 46.06, + "lng": 14.51, "reporting": { - "label": "ICT4Peace Publications", - "url": "https://ict4peace.org/" + "label": "Report to SI-CERT", + "url": "https://www.cert.si/en/report/" } }, { - "type": "html-list", - "followRedirects": true, + "type": "rss", "source": { - "source_id": "cida-africa-updates", - "authority_name": "CIDA Africa", - "country": "South Africa", - "country_code": "ZA", - "region": "Africa", - "authority_type": "public_safety_program", - "base_url": "https://cida-africa.org" + "source_id": "dnsc-ro", + "authority_name": "DNSC Romania", + "country": "Romania", + "country_code": "RO", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://dnsc.ro" }, - "feed_url": "https://cida-africa.org/", - "feed_urls": [ - "https://cida-africa.org/", - "https://cida-africa.org/news/" - ], + "feed_url": "https://dnsc.ro/feed", "category": "cyber_advisory", - "region_tag": "ZA", - "lat": -26.2041, - "lng": 28.0473, - "max_items": 80, - "include_keywords": [ - "cyber", - "security", - "incident", - "resilience", - "capacity", - "training", - "civil society" - ], - "exclude_keywords": [ - "privacy policy", - "terms", - "donate" - ], + "region_tag": "RO", + "lat": 44.43, + "lng": 26.1, "reporting": { - "label": "Contact CIDA Africa", - "url": "https://cida-africa.org/contact/" + "label": "Report to DNSC", + "url": "https://dnsc.ro/sesizare" } }, { "type": "html-list", - "followRedirects": true, "source": { - "source_id": "digital-society-africa", - "authority_name": "Digital Society of Africa", - "country": "Kenya", - "country_code": "KE", - "region": "Africa", - "authority_type": "public_safety_program", - "base_url": "https://digitalsociety.africa" + "source_id": "ncsc-ch", + "authority_name": "NCSC Switzerland", + "country": "Switzerland", + "country_code": "CH", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.ncsc.admin.ch" }, - "feed_url": "https://digitalsociety.africa/", - "feed_urls": [ - "https://digitalsociety.africa/", - "https://digitalsociety.africa/blog/" - ], + "feed_url": "https://www.ncsc.admin.ch/ncsc/en/home/aktuell/aktuelle-vorfaelle.html", "category": "cyber_advisory", - "region_tag": "KE", - "lat": -1.2864, - "lng": 36.8172, - "max_items": 80, - "include_keywords": [ - "digital security", - "cyber", - "safety", - "threat", - "awareness", - "training", - "response" - ], - "exclude_keywords": [ - "about us", - "privacy policy", - "terms" - ], + "region_tag": "CH", + "lat": 46.95, + "lng": 7.45, "reporting": { - "label": "Contact Digital Society Africa", - "url": "https://digitalsociety.africa/contact/" + "label": "Report to NCSC", + "url": "https://www.ncsc.admin.ch/ncsc/en/home/infos-fuer/infos-it-spezialisten/themen/schwachstelle-melden.html" } }, { - "type": "html-list", - "followRedirects": true, + "type": "rss", "source": { - "source_id": "resilio-africa", - "authority_name": "Resilio Africa", - "country": "Nigeria", - "country_code": "NG", - "region": "Africa", - "authority_type": "public_safety_program", - "base_url": "https://resilio.cybersafefoundation.org" + "source_id": "politi-dk", + "authority_name": "Danish Police", + "country": "Denmark", + "country_code": "DK", + "region": "Europe", + "authority_type": "police", + "base_url": "https://politi.dk" }, - "feed_url": "https://resilio.cybersafefoundation.org/", - "category": "cyber_advisory", - "region_tag": "NG", - "lat": 9.082, - "lng": 8.6753, - "max_items": 80, - "include_keywords": [ - "cyber", - "resilience", - "program", - "community", - "security", - "incident", - "capacity" - ], - "exclude_keywords": [ - "privacy", - "terms" + "feed_url": "https://politi.dk/rss", + "feed_urls": [ + "https://politi.dk/rss", + "https://politi.dk/nyheder/rss" ], + "category": "public_appeal", + "region_tag": "DK", + "lat": 55.68, + "lng": 12.57, "reporting": { - "label": "Contact Resilio Africa", - "url": "https://resilio.cybersafefoundation.org/" + "label": "Report to Danish Police", + "url": "https://politi.dk/anmeld", + "phone": "114" } }, { - "type": "html-list", - "followRedirects": true, + "type": "rss", "source": { - "source_id": "derechos-digitales-latam", - "authority_name": "Derechos Digitales", - "country": "Chile", - "country_code": "CL", - "region": "South America", - "authority_type": "public_safety_program", - "base_url": "https://www.derechosdigitales.org" + "source_id": "poliisi-fi", + "authority_name": "Finnish Police", + "country": "Finland", + "country_code": "FI", + "region": "Europe", + "authority_type": "police", + "base_url": "https://poliisi.fi" }, - "feed_url": "https://www.derechosdigitales.org/noticias/", + "feed_url": "https://poliisi.fi/en/rss/news", "feed_urls": [ - "https://www.derechosdigitales.org/noticias/", - "https://www.derechosdigitales.org/categoria/seguridad-digital/" - ], - "category": "cyber_advisory", - "region_tag": "CL", - "lat": -33.4489, - "lng": -70.6693, - "max_items": 100, - "include_keywords": [ - "seguridad digital", - "resiliencia", - "proteccion", - "ciber", - "sociedad civil", - "amenaza" - ], - "exclude_keywords": [ - "donar", - "newsletter", - "equipo" + "https://poliisi.fi/en/rss/news", + "https://poliisi.fi/rss/uutiset" ], + "category": "public_appeal", + "region_tag": "FI", + "lat": 60.17, + "lng": 24.94, "reporting": { - "label": "Contact Derechos Digitales", - "url": "https://www.derechosdigitales.org/contacto/" + "label": "Report to Finnish Police", + "url": "https://poliisi.fi/en/report-a-crime", + "phone": "112" } }, { - "type": "html-list", - "followRedirects": true, + "type": "rss", "source": { - "source_id": "tedic-paraguay", - "authority_name": "TEDIC Paraguay", - "country": "Paraguay", - "country_code": "PY", - "region": "South America", - "authority_type": "public_safety_program", - "base_url": "https://www.tedic.org" + "source_id": "garda-ie", + "authority_name": "An Garda Síochána", + "country": "Ireland", + "country_code": "IE", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.garda.ie" }, - "feed_url": "https://www.tedic.org/noticias/", - "feed_urls": [ - "https://www.tedic.org/noticias/", - "https://www.tedic.org/tag/seguridad-digital/" - ], - "category": "cyber_advisory", - "region_tag": "PY", - "lat": -25.2637, - "lng": -57.5759, - "max_items": 100, - "include_keywords": [ - "seguridad digital", - "ciber", - "proteccion", - "sociedad civil", - "capacitacion", - "riesgo" - ], - "exclude_keywords": [ - "donar", - "equipo", - "convocatoria laboral" - ], + "feed_url": "https://www.garda.ie/en/about-us/our-departments/office-of-corporate-communications/press-releases/", + "category": "public_appeal", + "region_tag": "IE", + "lat": 53.34, + "lng": -6.26, "reporting": { - "label": "Contact TEDIC", - "url": "https://www.tedic.org/contacto/" + "label": "Report to An Garda Síochána", + "url": "https://www.garda.ie/en/contact-us/", + "phone": "999 / 112" } }, { - "type": "html-list", - "followRedirects": true, + "type": "rss", "source": { - "source_id": "karisma-colombia", - "authority_name": "Fundacion Karisma", - "country": "Colombia", - "country_code": "CO", - "region": "South America", - "authority_type": "public_safety_program", - "base_url": "https://web.karisma.org.co" + "source_id": "federale-politie-be", + "authority_name": "Belgian Federal Police", + "country": "Belgium", + "country_code": "BE", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.police.be" }, - "feed_url": "https://web.karisma.org.co/blog/", + "feed_url": "https://www.police.be/feeds/rss", "feed_urls": [ - "https://web.karisma.org.co/blog/", - "https://web.karisma.org.co/tag/seguridad-digital/" - ], - "category": "cyber_advisory", - "region_tag": "CO", - "lat": 4.711, - "lng": -74.0721, - "max_items": 100, - "include_keywords": [ - "seguridad digital", - "ciberseguridad", - "proteccion", - "organizaciones", - "amenaza", - "riesgo" - ], - "exclude_keywords": [ - "donaciones", - "equipo", - "vacante" + "https://www.police.be/feeds/rss", + "https://www.politie.be/feeds/rss" ], + "category": "public_appeal", + "region_tag": "BE", + "lat": 50.85, + "lng": 4.35, "reporting": { - "label": "Contact Fundacion Karisma", - "url": "https://web.karisma.org.co/contacto/" + "label": "Report to Belgian Police", + "url": "https://www.police.be/fr/contact", + "phone": "101 / 112" } }, { - "type": "html-list", - "followRedirects": true, + "type": "rss", "source": { - "source_id": "unicef-giga", - "authority_name": "UNICEF Giga", - "country": "Global", - "country_code": "INT", - "region": "International", - "authority_type": "public_safety_program", - "base_url": "https://giga.global" + "source_id": "pj-pt", + "authority_name": "Polícia Judiciária", + "country": "Portugal", + "country_code": "PT", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.policiajudiciaria.pt" }, - "feed_url": "https://giga.global/", - "feed_urls": [ - "https://giga.global/", - "https://giga.global/insights/", - "https://giga.global/projects/" - ], - "category": "education_digital_capacity", - "region_tag": "INT", - "lat": 20, - "lng": 0, - "max_items": 100, - "include_keywords": [ - "school connectivity", - "internet", - "digital divide", - "schools", - "education", - "mapping" - ], - "exclude_keywords": [ - "privacy policy", - "terms", - "careers" - ], + "feed_url": "https://www.policiajudiciaria.pt/feed/", + "category": "public_appeal", + "region_tag": "PT", + "lat": 38.72, + "lng": -9.14, "reporting": { - "label": "UNICEF Giga Opportunities", - "url": "https://giga.global/" + "label": "Report to PJ", + "url": "https://www.policiajudiciaria.pt/contactos/", + "phone": "112" } }, { "type": "html-list", - "followRedirects": true, "source": { - "source_id": "itu-digital-capacity", - "authority_name": "ITU Digital Development", - "country": "Global", - "country_code": "INT", - "region": "International", - "authority_type": "regulatory", - "base_url": "https://www.itu.int" + "source_id": "cert-ee", + "authority_name": "CERT-EE", + "country": "Estonia", + "country_code": "EE", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.ria.ee" }, - "feed_url": "https://www.itu.int/en/ITU-D/Pages/default.aspx", - "feed_urls": [ - "https://www.itu.int/en/ITU-D/Pages/default.aspx", - "https://www.itu.int/hub/category/bridging-the-digital-divide/", - "https://www.itu.int/hub/category/cybersecurity/" - ], - "category": "education_digital_capacity", - "region_tag": "INT", - "lat": 20, - "lng": 0, - "max_items": 120, - "include_keywords": [ - "digital skills", - "capacity", - "connectivity", - "cyber capacity", - "education", - "training" - ], - "exclude_keywords": [ - "meeting calendar", - "press release" - ], + "feed_url": "https://www.ria.ee/kuberturvalisus/kuberintsidentide-kasitlemine-cert-ee", + "category": "cyber_advisory", + "region_tag": "EE", + "lat": 59.44, + "lng": 24.75, "reporting": { - "label": "ITU Development Programs", - "url": "https://www.itu.int/en/ITU-D/Pages/default.aspx" + "label": "Report to CERT-EE", + "url": "https://www.ria.ee/en/cyber-security/cert-ee/reporting-incident" } }, { "type": "html-list", - "followRedirects": true, "source": { - "source_id": "worldbank-education-digital", - "authority_name": "World Bank Education Digital", - "country": "Global", - "country_code": "INT", - "region": "International", - "authority_type": "regulatory", - "base_url": "https://www.worldbank.org" + "source_id": "nksc-lt", + "authority_name": "NKSC Lithuania", + "country": "Lithuania", + "country_code": "LT", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.nksc.lt" }, - "feed_url": "https://www.worldbank.org/en/topic/education", - "feed_urls": [ - "https://www.worldbank.org/en/topic/education", - "https://www.worldbank.org/en/topic/digitaldevelopment" - ], - "category": "education_digital_capacity", - "region_tag": "INT", - "lat": 20, - "lng": 0, - "max_items": 120, - "include_keywords": [ - "education", - "digital", - "school", - "ICT", - "skills", - "capacity building" - ], - "exclude_keywords": [ - "annual report", - "procurement policy" - ], + "feed_url": "https://www.nksc.lt/en/threats.html", + "category": "cyber_advisory", + "region_tag": "LT", + "lat": 54.69, + "lng": 25.28, "reporting": { - "label": "World Bank Education Programs", - "url": "https://www.worldbank.org/en/topic/education" + "label": "Report to NKSC", + "url": "https://www.nksc.lt/en/report.html" } }, { "type": "html-list", - "followRedirects": true, "source": { - "source_id": "africa-code-week", - "authority_name": "Africa Code Week", - "country": "Africa", - "country_code": "AFR", - "region": "Africa", - "authority_type": "public_safety_program", - "base_url": "https://africacodeweek.org" + "source_id": "ncsa-gr", + "authority_name": "NCSA Greece", + "country": "Greece", + "country_code": "GR", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.nis.gr" }, - "feed_url": "https://africacodeweek.org/", - "feed_urls": [ - "https://africacodeweek.org/", - "https://africacodeweek.org/news/" - ], - "category": "education_digital_capacity", - "region_tag": "AFR", - "lat": 1.65, - "lng": 17, - "max_items": 100, - "include_keywords": [ - "mentor", - "teacher", - "volunteer", - "digital literacy", - "coding", - "training" - ], - "exclude_keywords": [ - "privacy", - "terms", - "sponsor package" - ], + "feed_url": "https://www.nis.gr/el/national-cert/", + "category": "cyber_advisory", + "region_tag": "GR", + "lat": 37.98, + "lng": 23.73, "reporting": { - "label": "Join Africa Code Week", - "url": "https://africacodeweek.org/" + "label": "Report to NCSA Greece", + "url": "https://www.nis.gr/el/contact/" } }, { "type": "html-list", - "followRedirects": true, "source": { - "source_id": "dot-digital-opportunity-trust", - "authority_name": "Digital Opportunity Trust", - "country": "Global", - "country_code": "INT", - "region": "International", - "authority_type": "public_safety_program", - "base_url": "https://www.dotrust.org" + "source_id": "govcert-bg", + "authority_name": "GovCERT Bulgaria", + "country": "Bulgaria", + "country_code": "BG", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.govcert.bg" }, - "feed_url": "https://www.dotrust.org/", - "feed_urls": [ - "https://www.dotrust.org/", - "https://www.dotrust.org/news/" - ], - "category": "education_digital_capacity", - "region_tag": "INT", - "lat": 20, - "lng": 0, - "max_items": 100, - "include_keywords": [ - "digital skills", - "training", - "youth", - "employment", - "mentor", - "capacity" - ], - "exclude_keywords": [ - "donate", - "annual report" - ], + "feed_url": "https://www.govcert.bg/", + "category": "cyber_advisory", + "region_tag": "BG", + "lat": 42.7, + "lng": 23.32, "reporting": { - "label": "DOT Programs and Partnerships", - "url": "https://www.dotrust.org/" + "label": "Report to GovCERT.bg", + "url": "https://www.govcert.bg/" } }, { - "type": "html-list", - "followRedirects": true, + "type": "travelwarning-json", "source": { - "source_id": "european-schoolnet", - "authority_name": "European Schoolnet", - "country": "Europe", - "country_code": "EU", + "source_id": "de-aa-travel", + "authority_name": "German Federal Foreign Office", + "country": "Germany", + "country_code": "DE", "region": "Europe", - "authority_type": "public_safety_program", - "base_url": "https://www.eun.org" + "authority_type": "national_security", + "base_url": "https://www.auswaertiges-amt.de" }, - "feed_url": "https://www.eun.org/", - "feed_urls": [ - "https://www.eun.org/", - "https://www.eun.org/news" - ], - "category": "education_digital_capacity", - "region_tag": "EU", - "lat": 50.85, - "lng": 4.35, - "max_items": 100, - "include_keywords": [ - "digital education", - "teacher training", - "skills", - "school", - "capacity" - ], - "exclude_keywords": [ - "privacy policy", - "cookie policy" - ], + "feed_url": "https://www.auswaertiges-amt.de/opendata/travelwarning", + "category": "travel_warning", + "region_tag": "DE", + "lat": 52.52, + "lng": 13.405, "reporting": { - "label": "European Schoolnet Initiatives", - "url": "https://www.eun.org/" + "label": "German Federal Foreign Office", + "url": "https://www.auswaertiges-amt.de/en/aussenpolitik/laenderinformationen", + "notes": "Travel and safety information for German citizens abroad." } }, { - "type": "html-list", - "followRedirects": true, + "type": "travelwarning-atom", "source": { - "source_id": "erasmus-plus-digital", - "authority_name": "Erasmus+ Digital Education", - "country": "Europe", - "country_code": "EU", + "source_id": "uk-fcdo-travel", + "authority_name": "UK FCDO Travel Advice", + "country": "United Kingdom", + "country_code": "GB", "region": "Europe", - "authority_type": "regulatory", - "base_url": "https://erasmus-plus.ec.europa.eu" + "authority_type": "national_security", + "base_url": "https://www.gov.uk" }, - "feed_url": "https://erasmus-plus.ec.europa.eu/", - "feed_urls": [ - "https://erasmus-plus.ec.europa.eu/", - "https://erasmus-plus.ec.europa.eu/opportunities" - ], - "category": "education_digital_capacity", - "region_tag": "EU", - "lat": 50.85, - "lng": 4.35, - "max_items": 120, - "include_keywords": [ - "digital", - "education", - "training", - "call", - "project", - "skills" - ], - "exclude_keywords": [ - "about", - "legal notice" - ], + "feed_url": "https://www.gov.uk/government/organisations/foreign-commonwealth-development-office.atom", + "category": "travel_warning", + "region_tag": "GB", + "lat": 51.5074, + "lng": -0.1278, "reporting": { - "label": "Erasmus+ Opportunities", - "url": "https://erasmus-plus.ec.europa.eu/opportunities" + "label": "UK FCDO Travel Advice", + "url": "https://www.gov.uk/foreign-travel-advice", + "notes": "Travel advice and safety information for British nationals." } }, { "type": "html-list", "followRedirects": true, "source": { - "source_id": "coe-education-digital", - "authority_name": "Council of Europe Education", - "country": "Europe", - "country_code": "EU", - "region": "Europe", - "authority_type": "regulatory", - "base_url": "https://www.coe.int" + "source_id": "us-state-travel", + "authority_name": "US State Dept Travel Advisories", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "national_security", + "base_url": "https://travel.state.gov" }, - "feed_url": "https://www.coe.int/en/web/education", - "feed_urls": [ - "https://www.coe.int/en/web/education", - "https://www.coe.int/en/web/digital-citizenship-education" - ], - "category": "education_digital_capacity", - "region_tag": "EU", - "lat": 48.58, - "lng": 7.75, - "max_items": 100, + "feed_url": "https://travel.state.gov/content/travel/en/traveladvisories/traveladvisories.html", + "category": "travel_warning", + "region_tag": "US", + "lat": 38.9, + "lng": -77.05, "include_keywords": [ - "digital citizenship", - "education", - "training", - "school", - "online safety" - ], - "exclude_keywords": [ - "press room", - "vacancy" + "travel advisory", + "level", + "do not travel", + "reconsider", + "exercise caution" ], "reporting": { - "label": "Council of Europe Education Programs", - "url": "https://www.coe.int/en/web/education" + "label": "US State Department Travel Advisories", + "url": "https://travel.state.gov/content/travel/en/traveladvisories/traveladvisories.html", + "notes": "Travel advisories for US citizens abroad." } } ] diff --git a/src/App.tsx b/src/App.tsx index 5ca4f14..a4bc143 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,54 +4,148 @@ * See NOTICE for provenance and LICENSE for repository-local terms. */ -import { useCallback, useEffect, useRef, useState } from "react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { Header } from "@/components/Header"; -import { StatsBar } from "@/components/StatsBar"; import { GlobeView } from "@/components/GlobeView"; import { AlertFeed } from "@/components/AlertFeed"; import { AlertDetail } from "@/components/AlertDetail"; -import { SubmitIntelModal } from "@/components/SubmitIntelModal"; +import { FeedDirectory } from "@/components/FeedDirectory"; import { useAlerts } from "@/hooks/useAlerts"; +import { useSourceHealth } from "@/hooks/useSourceHealth"; +import { alertMatchesRegionFilter } from "@/lib/regions"; +import type { AlertCategory } from "@/types/alert"; + +const SOURCE_SELECTION_COOKIE = "euosint_selected_sources"; + +function readSelectedSources(): string[] { + if (typeof document === "undefined") return []; + const cookie = document.cookie + .split("; ") + .find((entry) => entry.startsWith(`${SOURCE_SELECTION_COOKIE}=`)); + if (!cookie) return []; + try { + const value = decodeURIComponent(cookie.split("=").slice(1).join("=")); + const parsed = JSON.parse(value); + return Array.isArray(parsed) + ? parsed.filter((item): item is string => typeof item === "string" && item.trim().length > 0) + : []; + } catch { + return []; + } +} + +function writeSelectedSources(sourceIds: string[]) { + if (typeof document === "undefined") return; + const expires = new Date(); + expires.setMonth(expires.getMonth() + 6); + document.cookie = `${SOURCE_SELECTION_COOKIE}=${encodeURIComponent(JSON.stringify(sourceIds))}; expires=${expires.toUTCString()}; path=/; SameSite=Lax`; +} export default function App() { const { alerts, isLoading, sourceCount } = useAlerts(); + const { sourceHealth, isLoading: isSourceHealthLoading } = useSourceHealth(); const [selectedId, setSelectedId] = useState(null); - const [regionFilter, setRegionFilter] = useState("all"); + const [selectedSourceIds, setSelectedSourceIds] = useState([]); + const [categoryFilter, setCategoryFilter] = useState("all"); + const [regionFilter, setRegionFilter] = useState("Europe"); + const [searchQuery, setSearchQuery] = useState(""); const [visibleAlertIds, setVisibleAlertIds] = useState([]); - const [mobilePane, setMobilePane] = useState<"map" | "stack">("map"); - const [isDesktopFeedOpen, setIsDesktopFeedOpen] = useState(true); - const [feedVisible, setFeedVisible] = useState(true); - const [feedToggled, setFeedToggled] = useState(false); - const [isSubmitOpen, setIsSubmitOpen] = useState(false); + const [mobilePane, setMobilePane] = useState<"intel" | "map" | "alerts">("map"); const panelRef = useRef(null); - const feedRef = useRef(null); + + useEffect(() => { + setSelectedSourceIds(readSelectedSources()); + }, []); + + useEffect(() => { + const availableSourceIds = new Set(alerts.map((alert) => alert.source_id)); + setSelectedSourceIds((current) => { + const next = current.filter((sourceId) => availableSourceIds.has(sourceId)); + if (next.length !== current.length) { + writeSelectedSources(next); + } + return next; + }); + }, [alerts]); + + useEffect(() => { + writeSelectedSources(selectedSourceIds); + }, [selectedSourceIds]); + + const handleRegionChange = useCallback((nextRegion: string) => { + setRegionFilter(nextRegion); + setSelectedSourceIds([]); + setSelectedId(null); + }, []); + + const regionScopedAlerts = useMemo(() => { + let filtered = alerts; + if (regionFilter !== "all") { + filtered = filtered.filter((alert) => alertMatchesRegionFilter(alert, regionFilter)); + } + const query = searchQuery.trim().toLowerCase(); + if (query) { + filtered = filtered.filter((alert) => { + const haystack = [ + alert.title, + alert.source.authority_name, + alert.source.country, + alert.source.country_code, + alert.source.region, + alert.category, + alert.canonical_url, + ] + .join(" ") + .toLowerCase(); + return haystack.includes(query); + }); + } + return filtered; + }, [alerts, regionFilter, searchQuery]); + + const scopedAlerts = useMemo(() => { + let filtered = regionScopedAlerts; + if (selectedSourceIds.length > 0) { + const selectedSet = new Set(selectedSourceIds); + filtered = filtered.filter((alert) => selectedSet.has(alert.source_id)); + } + if (categoryFilter !== "all") { + filtered = filtered.filter((alert) => alert.category === categoryFilter); + } + return filtered; + }, [categoryFilter, regionScopedAlerts, selectedSourceIds]); + + const handleCountrySelect = useCallback((countryCode: string) => { + const nextRegion = `country:${countryCode}`; + setRegionFilter((current) => current === nextRegion ? "all" : nextRegion); + setSelectedSourceIds([]); + setCategoryFilter("all"); + setSelectedId(null); + }, []); + + const handleSourceSelectionChange = useCallback((sourceIds: string[]) => { + setSelectedSourceIds(sourceIds); + setSelectedId(null); + }, []); + const selectedAlert = selectedId - ? alerts.find((a) => a.alert_id === selectedId) ?? null + ? scopedAlerts.find((a) => a.alert_id === selectedId) ?? alerts.find((a) => a.alert_id === selectedId) ?? null : null; const handleClose = useCallback(() => { const el = panelRef.current; - if (!el) { setSelectedId(null); return; } - el.style.animation = "slide-out-right 0.3s ease-in forwards"; - el.addEventListener("animationend", () => { + if (!el) { setSelectedId(null); - }, { once: true }); - }, []); - - const handleHideFeed = useCallback(() => { - setFeedToggled(true); - setFeedVisible(false); - const el = feedRef.current; - if (!el) { setIsDesktopFeedOpen(false); return; } - el.addEventListener("animationend", () => { - setIsDesktopFeedOpen(false); - }, { once: true }); - }, []); - - const handleShowFeed = useCallback(() => { - setFeedToggled(true); - setIsDesktopFeedOpen(true); - setFeedVisible(true); + return; + } + el.style.animation = "slide-out-right 0.24s ease-in forwards"; + el.addEventListener( + "animationend", + () => { + setSelectedId(null); + }, + { once: true } + ); }, []); useEffect(() => { @@ -61,126 +155,126 @@ export default function App() { }, [alerts, selectedId]); useEffect(() => { - setVisibleAlertIds(alerts.map((a) => a.alert_id)); - }, [alerts]); + setVisibleAlertIds(scopedAlerts.map((a) => a.alert_id)); + }, [scopedAlerts]); return ( -
- {/* Top Bar */} -
setIsSubmitOpen(true)} /> - -
-
- - -
-
+
+
{}} + alerts={alerts} + /> - {/* Main Content */} -
- {!isDesktopFeedOpen && ( - - )} - {/* Left Panel: Alert Feed */} - {(isDesktopFeedOpen || mobilePane === "stack") && ( -
- {isLoading ? ( -
- Loading live feed... -
- ) : ( - - )} + {/* Main content — fills remaining height, no overflow */} +
+ {/* Left panel — intel overview */} +
+
- )} - {/* Center: Globe (full remaining width) */} -
+ {/* Center — map */} +
- {/* Right Panel: Slide-out Alert Detail */} + {/* Right panel — alert queue (contained, scrollable) */} +
+
+ {isLoading ? ( +
+ Loading live alert queue... +
+ ) : ( + + )} +
+
+ + {/* Mobile tab bar */} +
+ {[ + ["intel", "Intel"], + ["map", "Map"], + ["alerts", "Queue"], + ].map(([pane, label]) => ( + + ))} +
+ + {/* Alert detail overlay */} {selectedAlert && (
- {/* Backdrop click to close */}
-
- +
+
)}
- setIsSubmitOpen(false)} /> - - {/* Bottom Status Bar */} -
- EUOSINT v0.1.0 +
+ Open Source Intelligence // World monitor - Sources: {sourceCount} authorities // Live feed // No data stored // Index + Link only + {selectedSourceIds.length > 0 + ? `Scoped to ${selectedSourceIds.length} feeds` + : categoryFilter !== "all" + ? `Scoped to ${categoryFilter}` + : "All live feeds"} - {sourceCount} src
); diff --git a/src/components/AlertFeed.tsx b/src/components/AlertFeed.tsx index 9a863a1..43b27f8 100644 --- a/src/components/AlertFeed.tsx +++ b/src/components/AlertFeed.tsx @@ -7,7 +7,7 @@ import { useEffect, useMemo, useRef, useState } from "react"; import type { Alert, AlertCategory, Severity } from "@/types/alert"; import { - severityColors, + severityColor, severityBg, severityLabel, categoryLabels, @@ -22,24 +22,25 @@ interface Props { alerts: Alert[]; selectedId: string | null; onSelect: (id: string) => void; + categoryFilter: AlertCategory | "all"; + onCategoryChange: (category: AlertCategory | "all") => void; regionFilter: string; onRegionChange: (region: string) => void; onVisibleAlertIdsChange: (ids: string[]) => void; - onHideDesktop?: () => void; } export function AlertFeed({ alerts, selectedId, onSelect, + categoryFilter, + onCategoryChange, regionFilter, onRegionChange, onVisibleAlertIdsChange, - onHideDesktop, }: Props) { const [viewMode, setViewMode] = useState<"navigator" | "timeline">("navigator"); const [actionableOnly, setActionableOnly] = useState(true); - const [categoryFilter, setCategoryFilter] = useState("all"); const [severityFilter, setSeverityFilter] = useState("all"); const [activeNavigatorGroupKey, setActiveNavigatorGroupKey] = useState(null); const [collapsedSections, setCollapsedSections] = useState>(new Set()); @@ -59,6 +60,22 @@ export function AlertFeed({ return [...set.entries()].sort((a, b) => b[1] - a[1]); }, [alerts]); + const countries = useMemo(() => { + const set = new Map(); + alerts.forEach((a) => { + const key = a.source.country_code; + const existing = set.get(key); + if (existing) { + existing.count++; + } else { + set.set(key, { name: a.source.country, count: 1 }); + } + }); + return [...set.entries()] + .map(([code, { name, count }]) => ({ code, name, count })) + .sort((a, b) => b.count - a.count); + }, [alerts]); + const regionFiltered = regionFilter === "all" ? alerts @@ -159,11 +176,12 @@ export function AlertFeed({ ); useEffect(() => { + const glowTimeouts = glowTimeoutsRef.current; return () => { if (refreshTimeoutRef.current) { window.clearTimeout(refreshTimeoutRef.current); } - glowTimeoutsRef.current.forEach((id) => window.clearTimeout(id)); + glowTimeouts.forEach((id) => window.clearTimeout(id)); }; }, []); @@ -206,13 +224,7 @@ export function AlertFeed({ knownAlertIdsRef.current = currentIds; }, [alerts]); - const severityRail: Record = { - critical: severityColors.critical, - high: severityColors.high, - medium: severityColors.medium, - low: severityColors.low, - info: severityColors.info, - }; + const severityRail = (s: Severity) => severityColor(s); useEffect(() => { const sig = visibleAlertIds.join("|"); @@ -235,7 +247,7 @@ export function AlertFeed({ >
@@ -303,15 +315,15 @@ export function AlertFeed({

- SOC Alert Stack + Intelligence Queue

- +
+ {regionFilter === "all" + ? "Global scope" + : regionFilter.startsWith("country:") + ? `${countries.find((c) => c.code === regionFilter.slice(8))?.name ?? regionFilter.slice(8)} scope` + : `${regionFilter} scope`} +
@@ -333,19 +345,27 @@ export function AlertFeed({ onChange={(e) => onRegionChange(e.target.value)} className="w-full appearance-none bg-white/5 border border-siem-border rounded-md pl-7 pr-8 py-1.5 text-xs text-siem-text cursor-pointer hover:bg-siem-accent/10 transition-colors focus:outline-none focus:ring-1 focus:ring-siem-accent" > - + {regions.map(([region, count]) => ( ))} + {countries.length > 0 && ( + + )} + {countries.map((c) => ( + + ))}
setHotspotTypeFilter(e.target.value)} - className="w-full appearance-none bg-white/5 border border-siem-border rounded-md px-2 py-1 text-[11px] text-siem-text" - > - - {hotspotTypeOptions.map((type) => ( - - ))} - - +
-
- {hotspotFiltered.map((alert) => ( - - ))} -
-
- )} - {/* Legend */} -
- {( - [ - ["critical", "bg-red-500"], - ["high", "bg-orange-500"], - ["medium", "bg-yellow-500"], - ["low", "bg-green-500"], - ["info", "bg-cyan-500"], - ] as const - ).map(([sev, bg]) => ( -
-
- {sev} + ))} +
- ))} -
-
- Drag to rotate · Scroll to zoom · Click a continent to filter -
-
- - -
-
- - {regions.map(([region]) => ( - - ))} -
-
- +
-
+ ); } diff --git a/src/components/Header.tsx b/src/components/Header.tsx index db59076..da545c9 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -4,53 +4,538 @@ * See NOTICE for provenance and LICENSE for repository-local terms. */ -import { Shield, Globe, Send } from "lucide-react"; +import { useEffect, useMemo, useRef, useState } from "react"; +import { Globe2, Radar, Search, Shield, X } from "lucide-react"; +import type { Alert } from "@/types/alert"; + +type MenuView = "overview" | "feeds" | "authorities" | "health"; interface Props { regionFilter: string; - onSubmitIntel: () => void; + onRegionChange: (region: string) => void; + sourceCount: number; + selectedSourceIds: string[]; + onSelectedSourceIdsChange: (sourceIds: string[]) => void; + searchQuery: string; + onSearchChange: (query: string) => void; + activeMenu: MenuView; + onMenuChange: (view: MenuView) => void; + alerts: Alert[]; +} + +const REGIONS = [ + "Europe", + "all", + "North America", + "South America", + "Africa", + "Asia", + "Oceania", + "Caribbean", + "International", +]; + +const _MENU_ITEMS: { key: MenuView; label: string }[] = [ + { key: "overview", label: "Overview" }, + { key: "feeds", label: "Feeds" }, + { key: "authorities", label: "Authorities" }, + { key: "health", label: "Source Health" }, +]; + +const SEARCH_HISTORY_COOKIE = "euosint_search_history"; + +function readSearchHistory(): string[] { + if (typeof document === "undefined") return []; + const cookie = document.cookie + .split("; ") + .find((entry) => entry.startsWith(`${SEARCH_HISTORY_COOKIE}=`)); + if (!cookie) return []; + try { + const value = decodeURIComponent(cookie.split("=").slice(1).join("=")); + const parsed = JSON.parse(value); + return Array.isArray(parsed) ? parsed.filter((item): item is string => typeof item === "string") : []; + } catch { + return []; + } +} + +function writeSearchHistory(history: string[]) { + if (typeof document === "undefined") return; + const expires = new Date(); + expires.setMonth(expires.getMonth() + 6); + document.cookie = `${SEARCH_HISTORY_COOKIE}=${encodeURIComponent(JSON.stringify(history))}; expires=${expires.toUTCString()}; path=/; SameSite=Lax`; } -export function Header({ regionFilter, onSubmitIntel }: Props) { +function FeedFocus({ + alerts, + sourceCount, + selectedSourceIds, + onSelectedSourceIdsChange, +}: { + alerts: Alert[]; + sourceCount: number; + selectedSourceIds: string[]; + onSelectedSourceIdsChange: (sourceIds: string[]) => void; +}) { + const [open, setOpen] = useState(false); + const [query, setQuery] = useState(""); + const containerRef = useRef(null); + const inputRef = useRef(null); + + const sources = useMemo(() => { + const map = new Map(); + for (const alert of alerts) { + const existing = map.get(alert.source_id); + if (existing) { + existing.count++; + } else { + map.set(alert.source_id, { + id: alert.source_id, + name: alert.source.authority_name, + country: alert.source.country, + count: 1, + }); + } + } + return [...map.values()].sort((a, b) => { + if (b.count !== a.count) return b.count - a.count; + return a.name.localeCompare(b.name); + }); + }, [alerts]); + + useEffect(() => { + const handler = (e: MouseEvent) => { + if (containerRef.current && !containerRef.current.contains(e.target as Node)) { + setOpen(false); + } + }; + document.addEventListener("mousedown", handler); + return () => document.removeEventListener("mousedown", handler); + }, []); + + const filteredSources = useMemo(() => { + const trimmed = query.trim().toLowerCase(); + if (!trimmed) return sources; + return sources.filter((source) => + `${source.name} ${source.country} ${source.id}`.toLowerCase().includes(trimmed), + ); + }, [query, sources]); + + const selectedLabels = useMemo(() => { + if (selectedSourceIds.length === 0) return `All ${sourceCount} authorities`; + const labels = selectedSourceIds + .map((sourceId) => sources.find((source) => source.id === sourceId)?.name ?? sourceId) + .slice(0, 2); + if (selectedSourceIds.length <= 2) return labels.join(", "); + return `${labels.join(", ")} +${selectedSourceIds.length - 2}`; + }, [selectedSourceIds, sourceCount, sources]); + + const toggleSource = (sourceId: string) => { + if (selectedSourceIds.includes(sourceId)) { + onSelectedSourceIdsChange(selectedSourceIds.filter((id) => id !== sourceId)); + return; + } + onSelectedSourceIdsChange([...selectedSourceIds, sourceId]); + }; + return ( -
-
-
- +
+
+
+ + Feed focus
-
-

EUOSINT

-

- EU-Focused Authority Bulletin Intelligence -

-
-
-
+
+ + {open && ( +
+
+ + setQuery(e.target.value)} + placeholder="Search feeds, agencies, countries..." + className="w-full bg-transparent pl-7 pr-7 py-1.5 text-xs text-siem-text placeholder:text-siem-muted/60 outline-none" + /> + {query && ( + + )} +
+
+ +
+
+ {filteredSources.length === 0 && ( +
No matching feeds
+ )} + {filteredSources.map((source) => { + const selected = selectedSourceIds.includes(source.id); + return ( + + ); + })} +
+
+ )} +
+ ); +} + +function SearchBar({ + query, + onQueryChange, +}: { + query: string; + onQueryChange: (query: string) => void; +}) { + const [isOpen, setIsOpen] = useState(false); + const [history, setHistory] = useState([]); + const containerRef = useRef(null); + const inputRef = useRef(null); + + useEffect(() => { + setHistory(readSearchHistory()); + }, []); + + useEffect(() => { + const handler = (e: MouseEvent) => { + if (containerRef.current && !containerRef.current.contains(e.target as Node)) { + setIsOpen(false); + } + }; + document.addEventListener("mousedown", handler); + return () => document.removeEventListener("mousedown", handler); + }, []); + + const filteredHistory = useMemo(() => { + const trimmed = query.trim().toLowerCase(); + if (!trimmed) return history; + return history.filter((item) => item.toLowerCase().includes(trimmed)); + }, [history, query]); + + const commitQuery = (value: string) => { + const trimmed = value.trim(); + onQueryChange(trimmed); + if (!trimmed) return; + const nextHistory = [trimmed, ...history.filter((item) => item !== trimmed)].slice(0, 8); + setHistory(nextHistory); + writeSearchHistory(nextHistory); + }; + + return ( +
+
{ + e.preventDefault(); + commitQuery(query); + setIsOpen(false); + }} + className="relative" + > + + onQueryChange(e.target.value)} + onFocus={() => setIsOpen(true)} + placeholder="Search alerts, agencies, countries, categories..." + className="w-full rounded-full border border-siem-border bg-siem-panel-strong pl-10 pr-24 py-3 text-sm text-siem-text outline-none transition-colors placeholder:text-siem-muted/60 focus:border-siem-accent/45" + /> + {query && ( + + )} + -
- - - {regionFilter === "all" ? "ALL REGIONS" : regionFilter} - + + + {isOpen && filteredHistory.length > 0 && ( +
+
+ Recent queries +
+
+ {filteredHistory.map((item) => ( + + ))} +
-
-
- - Monitoring - - - Live - + )} +
+ ); +} + +function RegionSearch({ + regionFilter, + onRegionChange, + alerts, +}: { + regionFilter: string; + onRegionChange: (region: string) => void; + alerts: Alert[]; +}) { + const [open, setOpen] = useState(false); + const [query, setQuery] = useState(""); + const containerRef = useRef(null); + const inputRef = useRef(null); + + // Build searchable items: regions + unique countries. + const items = useMemo(() => { + const regionItems = REGIONS.map((r) => ({ + value: r, + label: r === "all" ? "All regions" : r, + type: "region" as const, + count: r === "all" ? alerts.length : alerts.filter((a) => a.source.region === r).length, + })); + + const countryMap = new Map(); + for (const a of alerts) { + const key = a.source.country_code; + const existing = countryMap.get(key); + if (existing) { + existing.count++; + } else { + countryMap.set(key, { country: a.source.country, code: a.source.country_code, count: 1 }); + } + } + const countryItems = [...countryMap.values()] + .sort((a, b) => b.count - a.count) + .map((c) => ({ + value: `country:${c.code}`, + label: `${c.country} (${c.code})`, + type: "country" as const, + count: c.count, + })); + + return [...regionItems, ...countryItems]; + }, [alerts]); + + const filtered = useMemo(() => { + const q = query.toLowerCase().trim(); + if (!q) return items.filter((i) => i.count > 0 || i.type === "region"); + return items.filter((i) => i.label.toLowerCase().includes(q)); + }, [items, query]); + + // Close dropdown on outside click. + useEffect(() => { + const handler = (e: MouseEvent) => { + if (containerRef.current && !containerRef.current.contains(e.target as Node)) { + setOpen(false); + } + }; + document.addEventListener("mousedown", handler); + return () => document.removeEventListener("mousedown", handler); + }, []); + + const currentLabel = useMemo(() => { + if (regionFilter.startsWith("country:")) { + const code = regionFilter.slice(8); + const match = items.find((i) => i.value === regionFilter); + return match ? match.label : code; + } + return regionFilter === "all" ? "All regions" : regionFilter; + }, [regionFilter, items]); + + return ( +
+
+
+ + Region scope
+
+ + {open && ( +
+
+ + setQuery(e.target.value)} + placeholder="Search regions, countries\u2026" + className="w-full bg-transparent pl-7 pr-7 py-1.5 text-xs text-siem-text placeholder:text-siem-muted/60 outline-none" + /> + {query && ( + + )} +
+
+ {filtered.length === 0 && ( +
No matches
+ )} + {filtered.map((item) => ( + + ))} +
+
+ )}
); } + +export function Header({ + regionFilter, + onRegionChange, + sourceCount, + selectedSourceIds, + onSelectedSourceIdsChange, + searchQuery, + onSearchChange, + activeMenu, + onMenuChange, + alerts, +}: Props) { + return ( +
+
+
+
+
+ +
+
+
+ Scalytics Intelligence +
+
+ Open Source Intelligence +
+
+
+ +
+ +
+ +
+ + + +
+
+ +
+
+ ); +} diff --git a/src/components/StatsBar.tsx b/src/components/StatsBar.tsx index cce6414..80c9b6a 100644 --- a/src/components/StatsBar.tsx +++ b/src/components/StatsBar.tsx @@ -5,46 +5,72 @@ */ import type { Alert } from "@/types/alert"; -import { Shield, AlertTriangle, Globe, Radio, Clock } from "lucide-react"; +import type { SourceHealthDocument } from "@/types/source-health"; +import { Activity, AlertTriangle, Globe2, ShieldAlert, Siren, Workflow } from "lucide-react"; interface Props { alerts: Alert[]; + sourceHealth: SourceHealthDocument | null; } -export function StatsBar({ alerts }: Props) { - const total = alerts.length; - const critical = alerts.filter((a) => a.severity === "critical").length; - const high = alerts.filter((a) => a.severity === "high").length; - const active = alerts.filter((a) => a.status === "active").length; - const regions = new Set(alerts.map((a) => a.source.country_code)).size; - const agencyTypes = new Set(alerts.map((a) => a.source.authority_type)).size; - - const stats = [ - { icon: Radio, label: "ACTIVE ALERTS", value: active, color: "text-green-400" }, - { icon: AlertTriangle, label: "CRITICAL", value: critical, color: "text-red-400" }, - { icon: Shield, label: "HIGH", value: high, color: "text-orange-400" }, - { icon: Globe, label: "REGIONS", value: regions, color: "text-blue-400" }, - { icon: Shield, label: "AGENCY TYPES", value: agencyTypes, color: "text-siem-muted" }, - { icon: Clock, label: "TOTAL", value: total, color: "text-siem-muted" }, +export function StatsBar({ alerts, sourceHealth }: Props) { + const metrics = [ + { + icon: Activity, + label: "Active", + value: alerts.filter((alert) => alert.status === "active").length, + tone: "text-emerald-300", + }, + { + icon: AlertTriangle, + label: "Critical", + value: alerts.filter((alert) => alert.severity === "critical").length, + tone: "text-rose-300", + }, + { + icon: ShieldAlert, + label: "High", + value: alerts.filter((alert) => alert.severity === "high").length, + tone: "text-amber-300", + }, + { + icon: Globe2, + label: "Countries", + value: new Set(alerts.map((alert) => alert.source.country_code)).size, + tone: "text-siem-accent", + }, + { + icon: Workflow, + label: "Feeds OK", + value: sourceHealth?.sources_ok ?? 0, + tone: "text-siem-text", + }, + { + icon: Siren, + label: "Feed errors", + value: sourceHealth?.sources_error ?? 0, + tone: "text-siem-muted", + }, ]; return ( -
-
-
- - Live - -
- {stats.map((s) => ( -
- -
- {s.value} - {s.label} +
+
+ {metrics.map((metric) => ( +
+
+ + {metric.value} +
+
+ {metric.label} +
-
- ))} + ))} +
); } diff --git a/src/hooks/useSourceHealth.ts b/src/hooks/useSourceHealth.ts new file mode 100644 index 0000000..fecd6fe --- /dev/null +++ b/src/hooks/useSourceHealth.ts @@ -0,0 +1,49 @@ +/* + * EUOSINT + * Portions derived from novatechflow/osint-siem and cyberdude88/osint-siem. + * See NOTICE for provenance and LICENSE for repository-local terms. + */ + +import { useEffect, useState } from "react"; +import type { SourceHealthDocument } from "@/types/source-health"; + +const SOURCE_HEALTH_URL = `${import.meta.env.BASE_URL}source-health.json`; +const POLL_MS = 30000; + +export function useSourceHealth() { + const [document, setDocument] = useState(null); + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + let cancelled = false; + + async function load() { + try { + const response = await fetch(`${SOURCE_HEALTH_URL}?t=${Date.now()}`, { + cache: "no-store", + }); + if (!response.ok) { + throw new Error(`source health fetch failed: ${response.status}`); + } + const data = (await response.json()) as SourceHealthDocument; + if (!cancelled) { + setDocument(data); + setIsLoading(false); + } + } catch { + if (!cancelled) { + setIsLoading(false); + } + } + } + + load(); + const interval = window.setInterval(load, POLL_MS); + return () => { + cancelled = true; + window.clearInterval(interval); + }; + }, []); + + return { sourceHealth: document, isLoading }; +} diff --git a/src/index.css b/src/index.css index 6250d7e..c7a43f8 100644 --- a/src/index.css +++ b/src/index.css @@ -4,53 +4,91 @@ * See NOTICE for provenance and LICENSE for repository-local terms. */ +@import url("https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800&family=Roboto+Mono:wght@400;500;600&display=swap"); @import "tailwindcss"; @theme { - --color-siem-bg: #0a0e17; - --color-siem-panel: #111827; + /* ── Brand ──────────────────────────────────────────────────────── */ + --color-siem-bg: #070E1A; + --color-siem-panel: #0b1120; + --color-siem-panel-strong: #131d2e; --color-siem-border: #1e293b; - --color-siem-text: #e2e8f0; - --color-siem-muted: #64748b; - --color-siem-accent: #5f8fa3; - --color-siem-neutral: #7f9ca8; - --color-siem-critical: #d96464; - --color-siem-high: #d98958; - --color-siem-medium: #d1b35a; - --color-siem-low: #4eaf82; - --color-siem-info: #4fa0b1; + --color-siem-text: #e6edf5; + --color-siem-muted: #5A7B95; + --color-siem-accent: #E8630A; + --color-siem-accent-strong: #FF8533; + --color-siem-neutral: #9ca3af; + + /* ── Severity ───────────────────────────────────────────────────── */ + --color-siem-critical: #ff5d5d; + --color-siem-high: #f29d4b; + --color-siem-medium: #e3c867; + --color-siem-low: #4ccb8d; + --color-siem-info: #60a5fa; + + /* ── Category ───────────────────────────────────────────────────── */ + --color-cat-informational: #60a5fa; + --color-cat-cyber: #3b82f6; + --color-cat-education: #4f95a4; + --color-cat-humanitarian: #2f8c8c; + --color-cat-conflict: #725f95; + --color-cat-humsec: #3a7395; + --color-cat-wanted: #a14a5b; + --color-cat-missing: #aa8b43; + --color-cat-appeal: #5577a4; + --color-cat-fraud: #338c66; + --color-cat-safety: #5b6887; + --color-cat-terrorism: #a34c4c; + --color-cat-private: #8f6a46; + --color-cat-travel: #c27a3a; } * { - margin: 0; - padding: 0; box-sizing: border-box; } +html, +body, +#root { + min-height: 100dvh; +} + body { - font-family: 'Inter', system-ui, -apple-system, sans-serif; - background: var(--color-siem-bg); + margin: 0; + font-family: "Montserrat", "Segoe UI", sans-serif; + background: + radial-gradient(circle at top left, color-mix(in srgb, var(--color-siem-accent) 12%, transparent), transparent 32%), + radial-gradient(circle at top right, color-mix(in srgb, var(--color-siem-panel) 75%, transparent), transparent 26%), + var(--color-siem-bg); color: var(--color-siem-text); - overflow: hidden; - height: 100dvh; } -#root { - height: 100dvh; +button, +select, +input { + font: inherit; +} + +select option { + background: var(--color-siem-panel); + color: var(--color-siem-text); } ::-webkit-scrollbar { - width: 6px; + width: 8px; + height: 8px; } + ::-webkit-scrollbar-track { - background: var(--color-siem-bg); + background: color-mix(in srgb, var(--color-siem-panel) 75%, transparent); } + ::-webkit-scrollbar-thumb { - background: var(--color-siem-border); - border-radius: 3px; + background: color-mix(in srgb, var(--color-siem-accent) 25%, transparent); + border-radius: 999px; } -/* Slide-in animation for detail panel */ + @keyframes slide-in-right { from { transform: translateX(100%); @@ -74,94 +112,105 @@ body { } .animate-slide-in { - animation: slide-in-right 0.25s ease-out; -} - -.animate-slide-out { - animation: slide-out-right 0.25s ease-in forwards; -} - -/* Left panel slide */ -@keyframes slide-in-left { - from { transform: translateX(-100%); } - to { transform: translateX(0); } -} - -@keyframes slide-out-left { - from { transform: translateX(0); } - to { transform: translateX(-100%); } -} - -.feed-panel-open { - animation: slide-in-left 0.28s ease-out forwards; + animation: slide-in-right 0.26s ease-out; } -.feed-panel-closed { - animation: slide-out-left 0.28s ease-in forwards; -} - -@keyframes alert-list-refresh { - from { - transform: translateY(8px); - opacity: 0.78; - } - to { - transform: translateY(0); - opacity: 1; - } +.animate-alert-new-glow { + animation: alert-new-glow 1.8s ease-out forwards; } @keyframes alert-new-glow { 0% { - box-shadow: inset 0 0 0 1px rgba(147, 197, 253, 0.5), 0 0 0 rgba(59, 130, 246, 0); - background-color: rgba(59, 130, 246, 0.14); + box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--color-siem-accent) 55%, transparent), 0 0 24px color-mix(in srgb, var(--color-siem-accent) 16%, transparent); } 100% { - box-shadow: inset 0 0 0 1px rgba(147, 197, 253, 0), 0 0 0 rgba(59, 130, 246, 0); - background-color: transparent; + box-shadow: inset 0 0 0 1px transparent, 0 0 0 transparent; } } @keyframes critical-badge-pulse { 0% { transform: scale(1); - filter: brightness(1); } 50% { - transform: scale(1.035); - filter: brightness(1.15); + transform: scale(1.04); } 100% { transform: scale(1); - filter: brightness(1); } } -.animate-alert-list-refresh { - animation: alert-list-refresh 160ms ease-out; -} - -.animate-alert-new-glow { - animation: alert-new-glow 1.8s ease-out forwards; -} - .animate-critical-badge { - animation: critical-badge-pulse 2.2s ease-in-out infinite; - transform-origin: center; + animation: critical-badge-pulse 2s ease-in-out infinite; } @media (prefers-reduced-motion: reduce) { - .animate-alert-list-refresh, + .animate-slide-in, .animate-alert-new-glow, - .animate-critical-badge, - .feed-panel-open, - .feed-panel-closed { + .animate-critical-badge { animation: none !important; } } -/* Style the region dropdown options */ -select option { - background: #111827; - color: #e2e8f0; +/* ── Leaflet cluster overrides ──────────────────────────────────── */ + +.siem-cluster { + display: flex; + align-items: center; + justify-content: center; + border-radius: 50%; + font-family: "Roboto Mono", monospace; + font-weight: 600; + color: var(--color-siem-text); + border: 2px solid color-mix(in srgb, var(--color-siem-accent) 45%, transparent); +} + +.siem-cluster span { + line-height: 1; +} + +.siem-cluster-small { + font-size: 11px; + background: color-mix(in srgb, var(--color-siem-panel) 88%, transparent); +} + +.siem-cluster-medium { + font-size: 12px; + background: color-mix(in srgb, var(--color-siem-accent) 22%, transparent); +} + +.siem-cluster-large { + font-size: 13px; + background: color-mix(in srgb, var(--color-siem-high) 28%, transparent); + border-color: color-mix(in srgb, var(--color-siem-high) 55%, transparent); +} + +/* ── Leaflet tooltip ────────────────────────────────────────────── */ + +.siem-tooltip { + background: var(--color-siem-panel) !important; + border: 1px solid var(--color-siem-border) !important; + border-radius: 0.75rem !important; + color: var(--color-siem-text) !important; + font-family: "Montserrat", sans-serif !important; + font-size: 12px !important; + padding: 6px 10px !important; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.35) !important; +} + +.siem-tooltip::before { + border-top-color: var(--color-siem-border) !important; +} + +/* Hide default leaflet cluster styles that leak through */ +.marker-cluster-small, +.marker-cluster-medium, +.marker-cluster-large { + background: transparent !important; +} + +.marker-cluster-small div, +.marker-cluster-medium div, +.marker-cluster-large div { + background: transparent !important; } diff --git a/src/lib/regions.ts b/src/lib/regions.ts index ba45733..6eeaabf 100644 --- a/src/lib/regions.ts +++ b/src/lib/regions.ts @@ -52,6 +52,9 @@ export function latLngToRegion(lat: number, lng: number): string | null { export function alertMatchesRegionFilter(alert: Alert, regionFilter: string): boolean { if (regionFilter === "all") return true; + if (regionFilter.startsWith("country:")) { + return alert.source.country_code === regionFilter.slice(8); + } if (regionFilter === "Caribbean") { return ( alert.source.region === "Caribbean" || diff --git a/src/lib/severity.ts b/src/lib/severity.ts index 0452418..4a7e71a 100644 --- a/src/lib/severity.ts +++ b/src/lib/severity.ts @@ -5,21 +5,26 @@ */ import type { Severity, AlertCategory } from "@/types/alert"; +import { severityHex } from "@/lib/theme"; -export const severityColors: Record = { - critical: "#d96464", - high: "#d98958", - medium: "#d1b35a", - low: "#4eaf82", - info: "#4fa0b1", -}; +/** + * Get the resolved hex colour for a severity level. + * Reads from CSS custom properties at runtime — never hardcoded. + */ +export function severityColor(s: Severity): string { + return severityHex(s); +} +/** + * Tailwind class set for severity badge backgrounds. + * References @theme tokens so colours update from a single source. + */ export const severityBg: Record = { - critical: "bg-[#d96464]/15 text-[#d96464] border-[#d96464]/35", - high: "bg-[#d98958]/15 text-[#d98958] border-[#d98958]/35", - medium: "bg-[#d1b35a]/15 text-[#d1b35a] border-[#d1b35a]/35", - low: "bg-[#4eaf82]/15 text-[#4eaf82] border-[#4eaf82]/35", - info: "bg-[#4fa0b1]/15 text-[#4fa0b1] border-[#4fa0b1]/35", + critical: "bg-siem-critical/15 text-siem-critical border-siem-critical/35", + high: "bg-siem-high/15 text-siem-high border-siem-high/35", + medium: "bg-siem-medium/15 text-siem-medium border-siem-medium/35", + low: "bg-siem-low/15 text-siem-low border-siem-low/35", + info: "bg-siem-info/15 text-siem-info border-siem-info/35", }; export const severityLabel: Record = { @@ -44,6 +49,7 @@ export const categoryLabels: Record = { fraud_alert: "Fraud Alert", public_safety: "Public Safety", private_sector: "Private Sector", + travel_warning: "Travel Warning", }; export const categoryOrder: AlertCategory[] = [ @@ -60,22 +66,28 @@ export const categoryOrder: AlertCategory[] = [ "private_sector", "public_safety", "terrorism_tip", + "travel_warning", ]; +/** + * Tailwind class set for category badge backgrounds. + * References --color-cat-* tokens defined in @theme. + */ export const categoryBadge: Record = { - informational: "bg-cyan-500/15 text-cyan-300 border-cyan-500/30", - cyber_advisory: "bg-sky-500/15 text-sky-300 border-sky-500/30", - education_digital_capacity: "bg-cyan-500/15 text-cyan-300 border-cyan-500/30", - humanitarian_tasking: "bg-teal-500/15 text-teal-300 border-teal-500/30", - conflict_monitoring: "bg-fuchsia-500/15 text-fuchsia-300 border-fuchsia-500/30", - humanitarian_security: "bg-blue-500/15 text-blue-300 border-blue-500/30", - wanted_suspect: "bg-rose-500/15 text-rose-300 border-rose-500/30", - missing_person: "bg-amber-500/15 text-amber-300 border-amber-500/30", - public_appeal: "bg-indigo-500/15 text-indigo-300 border-indigo-500/30", - fraud_alert: "bg-emerald-500/15 text-emerald-300 border-emerald-500/30", - public_safety: "bg-violet-500/15 text-violet-300 border-violet-500/30", - terrorism_tip: "bg-red-500/15 text-red-300 border-red-500/30", - private_sector: "bg-orange-500/15 text-orange-300 border-orange-500/30", + informational: "bg-cat-informational/15 text-cat-informational border-cat-informational/30", + cyber_advisory: "bg-cat-cyber/15 text-cat-cyber border-cat-cyber/30", + education_digital_capacity: "bg-cat-education/15 text-cat-education border-cat-education/30", + humanitarian_tasking: "bg-cat-humanitarian/15 text-cat-humanitarian border-cat-humanitarian/30", + conflict_monitoring: "bg-cat-conflict/15 text-cat-conflict border-cat-conflict/30", + humanitarian_security: "bg-cat-humsec/15 text-cat-humsec border-cat-humsec/30", + wanted_suspect: "bg-cat-wanted/15 text-cat-wanted border-cat-wanted/30", + missing_person: "bg-cat-missing/15 text-cat-missing border-cat-missing/30", + public_appeal: "bg-cat-appeal/15 text-cat-appeal border-cat-appeal/30", + fraud_alert: "bg-cat-fraud/15 text-cat-fraud border-cat-fraud/30", + public_safety: "bg-cat-safety/15 text-cat-safety border-cat-safety/30", + terrorism_tip: "bg-cat-terrorism/15 text-cat-terrorism border-cat-terrorism/30", + private_sector: "bg-cat-private/15 text-cat-private border-cat-private/30", + travel_warning: "bg-cat-travel/15 text-cat-travel border-cat-travel/30", }; export const categoryIcons: Record = { @@ -92,6 +104,7 @@ export const categoryIcons: Record = { fraud_alert: "BadgeDollarSign", public_safety: "Siren", private_sector: "Building", + travel_warning: "Plane", }; export function freshnessLabel(hours: number): string { diff --git a/src/lib/theme.ts b/src/lib/theme.ts new file mode 100644 index 0000000..784f00f --- /dev/null +++ b/src/lib/theme.ts @@ -0,0 +1,50 @@ +/* + * EUOSINT + * Portions derived from novatechflow/osint-siem and cyberdude88/osint-siem. + * See NOTICE for provenance and LICENSE for repository-local terms. + */ + +/** + * Runtime reader for CSS custom-property colours defined in index.css @theme. + * This is the only place JS code should obtain colour hex values — everything + * else references Tailwind theme classes or CSS variables directly. + */ + +import type { Severity } from "@/types/alert"; + +const SEVERITY_VARS: Record = { + critical: "--color-siem-critical", + high: "--color-siem-high", + medium: "--color-siem-medium", + low: "--color-siem-low", + info: "--color-siem-info", +}; + +let root: CSSStyleDeclaration | null = null; + +function getRoot(): CSSStyleDeclaration { + if (!root) { + root = getComputedStyle(document.documentElement); + } + return root; +} + +/** Read any `--color-*` CSS variable as a trimmed hex string. */ +export function cssColor(varName: string): string { + return getRoot().getPropertyValue(varName).trim(); +} + +/** Get the hex colour for a severity level, read from the CSS theme. */ +export function severityHex(severity: Severity): string { + return cssColor(SEVERITY_VARS[severity]); +} + +/** Get the hex colour for the brand accent, read from the CSS theme. */ +export function accentHex(): string { + return cssColor("--color-siem-accent"); +} + +/** Get the hex colour for the primary text, read from the CSS theme. */ +export function textHex(): string { + return cssColor("--color-siem-text"); +} diff --git a/src/main.tsx b/src/main.tsx index 9131167..bd543cd 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -4,13 +4,13 @@ * See NOTICE for provenance and LICENSE for repository-local terms. */ -import { StrictMode } from 'react' -import { createRoot } from 'react-dom/client' -import './index.css' -import App from './App.tsx' +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import "./index.css"; +import App from "./App.tsx"; -createRoot(document.getElementById('root')!).render( +createRoot(document.getElementById("root")!).render( - , -) + +); diff --git a/src/types/alert.ts b/src/types/alert.ts index 7c7c4b9..a0aeb94 100644 --- a/src/types/alert.ts +++ b/src/types/alert.ts @@ -19,7 +19,8 @@ export type AlertCategory = | "terrorism_tip" | "fraud_alert" | "public_safety" - | "private_sector"; + | "private_sector" + | "travel_warning"; export type AuthorityType = | "police" | "national_security" diff --git a/src/types/source-health.ts b/src/types/source-health.ts new file mode 100644 index 0000000..67ca22a --- /dev/null +++ b/src/types/source-health.ts @@ -0,0 +1,41 @@ +/* + * EUOSINT + * Portions derived from novatechflow/osint-siem and cyberdude88/osint-siem. + * See NOTICE for provenance and LICENSE for repository-local terms. + */ + +export interface DuplicateSample { + title: string; + count: number; +} + +export interface DuplicateAudit { + suppressed_variant_duplicates: number; + repeated_title_groups_in_active: number; + repeated_title_samples: DuplicateSample[]; +} + +export interface SourceHealthEntry { + source_id: string; + authority_name: string; + type: string; + status: "ok" | "error"; + fetched_count: number; + feed_url: string; + error?: string; + started_at: string; + finished_at: string; + active_count?: number; + filtered_count?: number; +} + +export interface SourceHealthDocument { + generated_at: string; + critical_source_prefixes: string[]; + fail_on_critical_source_gap: boolean; + total_sources: number; + sources_ok: number; + sources_error: number; + duplicate_audit: DuplicateAudit; + sources: SourceHealthEntry[]; +} From fa4fc486ec54680f7498eab5bc0fc1daaf41ca88 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 17:08:29 +0100 Subject: [PATCH 02/58] feat(ui): tighten alert navigation and overview --- docs/operations.md | 1 + src/App.tsx | 8 ++++ src/components/AlertFeed.tsx | 52 ++++++++++++++------ src/components/FeedDirectory.tsx | 82 ++++++++++++++++++-------------- 4 files changed, 93 insertions(+), 50 deletions(-) diff --git a/docs/operations.md b/docs/operations.md index c5ac4e9..a3425fe 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -74,6 +74,7 @@ If the VM only has `docker-compose`, adjust the unit commands accordingly. ## Operational Notes - The collector writes feed output into the `feed-data` volume shared with the web container. +- The UI footer freshness line is derived from `source-health.json.generated_at` and shows the age of the current collector snapshot. It is normal below 20 minutes, warning from 20 to 60 minutes, and stale above 60 minutes. - Discovery intake lives in [registry/source_candidates.json](/Users/alo/Development/scalytics/EUOSINT/registry/source_candidates.json). - Dead sources are written to the terminal DLQ in `source_dead_letter.json` and are not crawled again. - LLM-assisted source vetting is documented in [docs/source-vetting.md](/Users/alo/Development/scalytics/EUOSINT/docs/source-vetting.md). diff --git a/src/App.tsx b/src/App.tsx index a4bc143..c00f60d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -128,6 +128,13 @@ export default function App() { setSelectedId(null); }, []); + const handleNavigatorSelect = useCallback((nextRegion: string, nextCategory: AlertCategory) => { + setRegionFilter(nextRegion); + setCategoryFilter(nextCategory); + setSelectedSourceIds([]); + setSelectedId(null); + }, []); + const selectedAlert = selectedId ? scopedAlerts.find((a) => a.alert_id === selectedId) ?? alerts.find((a) => a.alert_id === selectedId) ?? null : null; @@ -221,6 +228,7 @@ export default function App() { onCategoryChange={setCategoryFilter} regionFilter={regionFilter} onRegionChange={handleRegionChange} + onNavigatorSelect={handleNavigatorSelect} onVisibleAlertIdsChange={setVisibleAlertIds} /> )} diff --git a/src/components/AlertFeed.tsx b/src/components/AlertFeed.tsx index 43b27f8..963ac0a 100644 --- a/src/components/AlertFeed.tsx +++ b/src/components/AlertFeed.tsx @@ -26,6 +26,7 @@ interface Props { onCategoryChange: (category: AlertCategory | "all") => void; regionFilter: string; onRegionChange: (region: string) => void; + onNavigatorSelect?: (region: string, category: AlertCategory) => void; onVisibleAlertIdsChange: (ids: string[]) => void; } @@ -37,6 +38,7 @@ export function AlertFeed({ onCategoryChange, regionFilter, onRegionChange, + onNavigatorSelect, onVisibleAlertIdsChange, }: Props) { const [viewMode, setViewMode] = useState<"navigator" | "timeline">("navigator"); @@ -169,6 +171,15 @@ export function AlertFeed({ const activeNavigatorGroup = navigatorGroups.find((group) => group.key === activeNavigatorGroupKey) ?? null; + const handleNavigatorGroupSelect = (groupKey: string) => { + setActiveNavigatorGroupKey(groupKey); + const group = navigatorGroups.find((entry) => entry.key === groupKey); + if (!group) { + return; + } + onNavigatorSelect?.(group.region, group.category); + }; + // Keep globe visibility aligned with current filters, not only the active navigator bucket. const visibleAlertIds = useMemo( () => facetFiltered.map((a) => a.alert_id), @@ -311,7 +322,7 @@ export function AlertFeed({ }; return ( -
+

@@ -407,11 +418,7 @@ export function AlertFeed({

-
+
- {viewMode === "navigator" ? ( + {viewMode === "navigator" && ( <>
@@ -461,12 +468,12 @@ export function AlertFeed({
Region + category navigation
-
+
{navigatorGroups.map((group) => (
)} + + )} +
+
+ {viewMode === "navigator" ? ( +
{activeNavigatorGroup && ( -
+

Case Queue

@@ -510,16 +527,23 @@ export function AlertFeed({ {activeNavigatorGroup.total}
-
+
{activeNavigatorGroup.alerts.map((alert, idx) => renderAlertCard(alert, "Case", idx) )}
)} - + {!activeNavigatorGroup && ( +
+

+ Select a region/category bucket to inspect its case queue +

+
+ )} +
) : ( - <> +
{grouped.map((group) => (
)} - +
)} {facetFiltered.length === 0 && (
diff --git a/src/components/FeedDirectory.tsx b/src/components/FeedDirectory.tsx index d82b680..7a6eaa6 100644 --- a/src/components/FeedDirectory.tsx +++ b/src/components/FeedDirectory.tsx @@ -4,14 +4,13 @@ * See NOTICE for provenance and LICENSE for repository-local terms. */ -import { useMemo } from "react"; +import { useEffect, useMemo, useState } from "react"; import { Activity, AlertTriangle, Globe2, Radar, ShieldAlert, - Siren, TrendingUp, } from "lucide-react"; import type { Alert, AlertCategory } from "@/types/alert"; @@ -46,6 +45,12 @@ export function FeedDirectory({ onSelectCountry, }: Props) { const sources = sourceHealth?.sources ?? []; + const [now, setNow] = useState(() => Date.now()); + + useEffect(() => { + const timer = window.setInterval(() => setNow(Date.now()), 60_000); + return () => window.clearInterval(timer); + }, []); /* ── Region-scoped alerts ──────────────────────────────────────── */ @@ -104,10 +109,32 @@ export function FeedDirectory({ onSelectSourceIdsChange([...selectedSourceIds, sourceId]); }; - const feedErrors = useMemo( - () => sources.filter((s) => s.status === "error"), - [sources], - ); + const snapshotStatus = useMemo(() => { + const generatedAt = sourceHealth?.generated_at?.trim(); + if (!generatedAt) { + return null; + } + const ts = Date.parse(generatedAt); + if (Number.isNaN(ts)) { + return null; + } + const ageMinutes = Math.max(0, Math.floor((now - ts) / 60_000)); + const tone = + ageMinutes > 60 ? "text-rose-300" : ageMinutes >= 20 ? "text-amber-300" : "text-siem-muted"; + const relative = + ageMinutes < 1 ? "just now" : ageMinutes === 1 ? "1 min old" : `${ageMinutes} min old`; + const exact = new Intl.DateTimeFormat(undefined, { + year: "numeric", + month: "2-digit", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + timeZone: "UTC", + timeZoneName: "short", + hour12: false, + }).format(new Date(ts)); + return { tone, relative, exact }; + }, [now, sourceHealth?.generated_at]); if (isLoading && !sourceHealth && regionAlerts.length === 0) { return ( @@ -159,17 +186,13 @@ export function FeedDirectory({
- {feedErrors.length > 0 ? ( - - ) : ( - - )} + {sourceHealth?.sources_ok ?? 0}/{sourceHealth?.total_sources ?? 0}
- Feeds OK{feedErrors.length > 0 ? ` (${feedErrors.length} err)` : ""} + Feeds OK
@@ -274,31 +297,18 @@ export function FeedDirectory({
- {/* ── Feed errors (if any) ────────────────────────────────── */} - {feedErrors.length > 0 && ( -
-
- - Feed errors ({feedErrors.length}) -
-
- {feedErrors.slice(0, 15).map((entry) => ( -
-
{entry.authority_name}
-
- {entry.error ?? "Unknown error"} -
-
- ))} - {feedErrors.length > 15 && ( -
- +{feedErrors.length - 15} more errors -
- )} -
-
- )}
+ + {snapshotStatus && ( +
+
+ Data snapshot: {snapshotStatus.relative} +
+
+ Last collector update: {snapshotStatus.exact} +
+
+ )} ); } From c211055c13c296d6d43d0b166560316bb193b91d Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 17:08:34 +0100 Subject: [PATCH 03/58] feat(collector): harden browser-backed source ingestion --- internal/collector/fetch/browser.go | 84 +++++++++ internal/collector/normalize/normalize.go | 171 +++++++++++++++++- .../collector/normalize/normalize_test.go | 32 ++++ internal/collector/run/run.go | 121 +++++++++---- internal/collector/run/run_test.go | 12 ++ internal/collector/translate/llm.go | 73 ++++++-- internal/collector/translate/llm_test.go | 20 +- internal/sourcedb/db.go | 13 ++ internal/sourcedb/db_test.go | 112 ++++++++++++ registry/curated_agencies.seed.json | 10 +- 10 files changed, 584 insertions(+), 64 deletions(-) diff --git a/internal/collector/fetch/browser.go b/internal/collector/fetch/browser.go index f43df90..3415d50 100644 --- a/internal/collector/fetch/browser.go +++ b/internal/collector/fetch/browser.go @@ -6,8 +6,11 @@ package fetch import ( "context" "fmt" + "strings" + "sync" "time" + "github.com/chromedp/cdproto/network" "github.com/chromedp/chromedp" ) @@ -61,6 +64,87 @@ func (b *BrowserClient) Text(ctx context.Context, url string, followRedirects bo return []byte(html), nil } +// CaptureJSONResponses opens a page in headless Chrome and collects JSON +// XHR/fetch responses whose URL contains the given substring. +func (b *BrowserClient) CaptureJSONResponses(ctx context.Context, pageURL string, urlContains string) ([][]byte, error) { + timeout := time.Duration(b.timeoutMS) * time.Millisecond + taskCtx, cancel := chromedp.NewContext(b.allocCtx) + defer cancel() + + taskCtx, cancelTimeout := context.WithTimeout(taskCtx, timeout) + defer cancelTimeout() + + var ( + mu sync.Mutex + seen = map[network.RequestID]string{} + bodies [][]byte + captureErr error + ) + + chromedp.ListenTarget(taskCtx, func(ev any) { + switch e := ev.(type) { + case *network.EventResponseReceived: + if !strings.Contains(e.Response.URL, urlContains) { + return + } + if e.Type != network.ResourceTypeXHR && e.Type != network.ResourceTypeFetch { + return + } + mu.Lock() + seen[e.RequestID] = e.Response.URL + mu.Unlock() + case *network.EventLoadingFinished: + mu.Lock() + _, ok := seen[e.RequestID] + mu.Unlock() + if !ok { + return + } + go func(requestID network.RequestID) { + var body []byte + err := chromedp.Run(taskCtx, chromedp.ActionFunc(func(ctx context.Context) error { + data, err := network.GetResponseBody(requestID).Do(ctx) + if err != nil { + return err + } + body = data + return nil + })) + mu.Lock() + defer mu.Unlock() + if err != nil { + if captureErr == nil { + captureErr = err + } + return + } + if len(body) > 0 { + bodies = append(bodies, body) + } + }(e.RequestID) + } + }) + + if err := chromedp.Run(taskCtx, + network.Enable(), + chromedp.Navigate(pageURL), + chromedp.WaitReady("body"), + chromedp.Sleep(5*time.Second), + ); err != nil { + return nil, fmt.Errorf("browser capture %s: %w", pageURL, err) + } + + mu.Lock() + defer mu.Unlock() + if len(bodies) == 0 && captureErr != nil { + return nil, fmt.Errorf("browser capture %s: %w", pageURL, captureErr) + } + if len(bodies) == 0 { + return nil, fmt.Errorf("browser capture %s: no matching JSON responses", pageURL) + } + return bodies, nil +} + // Close shuts down the browser allocator and releases Chrome processes. func (b *BrowserClient) Close() { if b.cancelCtx != nil { diff --git a/internal/collector/normalize/normalize.go b/internal/collector/normalize/normalize.go index 0b54ebb..0f89607 100644 --- a/internal/collector/normalize/normalize.go +++ b/internal/collector/normalize/normalize.go @@ -181,15 +181,21 @@ func KEVAlert(ctx Context, meta model.RegistrySource, cveID string, vulnName str return &alert } -func InterpolAlert(ctx Context, meta model.RegistrySource, title string, link string, countryCode string, summary string, tags []string) *model.Alert { +func InterpolAlert(ctx Context, meta model.RegistrySource, noticeID string, title string, link string, countryCode string, summary string, tags []string) *model.Alert { if strings.TrimSpace(title) == "" { return nil } alert := baseAlert(ctx, meta, title, firstNonEmpty(link, meta.Source.BaseURL), ctx.Now) alert.Severity = "critical" - alert.RegionTag = firstNonEmpty(countryCode, alert.RegionTag) - if strings.TrimSpace(countryCode) != "" { - alert.Source.CountryCode = strings.ToUpper(strings.TrimSpace(countryCode)) + if id := strings.TrimSpace(noticeID); id != "" { + alert.AlertID = meta.Source.SourceID + ":" + id + } + if code := normalizeCountryCode(countryCode); code != "" { + alert.RegionTag = code + alert.Source.CountryCode = code + if name := countryNameFromCode(code); name != "" { + alert.Source.Country = name + } } alert.Triage = score(ctx.Config, alert, FeedContext{ Summary: summary, @@ -279,6 +285,163 @@ func baseAlert(ctx Context, meta model.RegistrySource, title string, link string } } +func normalizeCountryCode(code string) string { + code = strings.ToUpper(strings.TrimSpace(code)) + if len(code) == 2 { + return code + } + return "" +} + +func countryNameFromCode(code string) string { + switch normalizeCountryCode(code) { + case "AF": + return "Afghanistan" + case "AL": + return "Albania" + case "AR": + return "Argentina" + case "AT": + return "Austria" + case "AU": + return "Australia" + case "BE": + return "Belgium" + case "BG": + return "Bulgaria" + case "BR": + return "Brazil" + case "CA": + return "Canada" + case "CH": + return "Switzerland" + case "CL": + return "Chile" + case "CN": + return "China" + case "CO": + return "Colombia" + case "CR": + return "Costa Rica" + case "CZ": + return "Czech Republic" + case "DE": + return "Germany" + case "DK": + return "Denmark" + case "DO": + return "Dominican Republic" + case "EC": + return "Ecuador" + case "EE": + return "Estonia" + case "EG": + return "Egypt" + case "ES": + return "Spain" + case "FI": + return "Finland" + case "FR": + return "France" + case "GB": + return "United Kingdom" + case "GE": + return "Georgia" + case "GH": + return "Ghana" + case "GR": + return "Greece" + case "GT": + return "Guatemala" + case "HR": + return "Croatia" + case "HU": + return "Hungary" + case "ID": + return "Indonesia" + case "IE": + return "Ireland" + case "IL": + return "Israel" + case "IN": + return "India" + case "IS": + return "Iceland" + case "IT": + return "Italy" + case "JP": + return "Japan" + case "KE": + return "Kenya" + case "KR": + return "South Korea" + case "LT": + return "Lithuania" + case "LU": + return "Luxembourg" + case "LV": + return "Latvia" + case "MA": + return "Morocco" + case "MT": + return "Malta" + case "MX": + return "Mexico" + case "MY": + return "Malaysia" + case "NG": + return "Nigeria" + case "NL": + return "Netherlands" + case "NO": + return "Norway" + case "NZ": + return "New Zealand" + case "PE": + return "Peru" + case "PH": + return "Philippines" + case "PL": + return "Poland" + case "PT": + return "Portugal" + case "RO": + return "Romania" + case "RS": + return "Serbia" + case "RU": + return "Russia" + case "SE": + return "Sweden" + case "SG": + return "Singapore" + case "SI": + return "Slovenia" + case "SK": + return "Slovakia" + case "TH": + return "Thailand" + case "TN": + return "Tunisia" + case "TR": + return "Turkey" + case "TW": + return "Taiwan" + case "UA": + return "Ukraine" + case "US": + return "United States" + case "UY": + return "Uruguay" + case "VE": + return "Venezuela" + case "ZA": + return "South Africa" + default: + return "" + } +} + func score(cfg config.Config, alert model.Alert, feed FeedContext) *model.Triage { text := strings.ToLower(strings.Join([]string{ alert.Title, diff --git a/internal/collector/normalize/normalize_test.go b/internal/collector/normalize/normalize_test.go index 55454a8..9c36053 100644 --- a/internal/collector/normalize/normalize_test.go +++ b/internal/collector/normalize/normalize_test.go @@ -5,6 +5,7 @@ package normalize import ( "testing" + "time" "github.com/scalytics/euosint/internal/collector/config" "github.com/scalytics/euosint/internal/collector/model" @@ -40,3 +41,34 @@ func TestFilterActiveUsesMissingPersonThreshold(t *testing.T) { t.Fatalf("unexpected filtered alerts %#v", filtered) } } + +func TestInterpolAlertUsesNoticeCountryAndStableID(t *testing.T) { + ctx := Context{Config: config.Default(), Now: time.Date(2026, 3, 16, 0, 0, 0, 0, time.UTC)} + meta := model.RegistrySource{ + Type: "interpol-yellow-json", + Category: "missing_person", + RegionTag: "INT", + Source: model.SourceMetadata{ + SourceID: "interpol-yellow", + AuthorityName: "INTERPOL Yellow Notices", + Country: "France", + CountryCode: "FR", + Region: "International", + AuthorityType: "police", + BaseURL: "https://www.interpol.int", + }, + } + alert := InterpolAlert(ctx, meta, "2026-17351", "INTERPOL Yellow Notice: Jane Doe", "https://www.interpol.int/How-we-work/Notices/Yellow-Notices/View-Yellow-Notices#2026-17351", "DE", "INTERPOL Paris", []string{"DE"}) + if alert == nil { + t.Fatal("expected interpol alert") + } + if alert.AlertID != "interpol-yellow:2026-17351" { + t.Fatalf("expected stable interpol alert id, got %q", alert.AlertID) + } + if alert.Source.CountryCode != "DE" || alert.Source.Country != "Germany" { + t.Fatalf("expected country mapping to Germany, got %#v", alert.Source) + } + if alert.Source.AuthorityName != "INTERPOL Yellow Notices" { + t.Fatalf("expected source authority to remain INTERPOL, got %#v", alert.Source) + } +} diff --git a/internal/collector/run/run.go b/internal/collector/run/run.go index 394cfe0..1e45d6c 100644 --- a/internal/collector/run/run.go +++ b/internal/collector/run/run.go @@ -102,7 +102,7 @@ func (r Runner) runOnce(ctx context.Context, cfg config.Config) error { for _, source := range sources { startedAt := time.Now().UTC() fetcher := fetch.FetcherFor(source.FetchMode, client, browser) - batch, err := r.fetchSource(ctx, fetcher, nctx, source, categoryDictionary) + batch, err := r.fetchSource(ctx, fetcher, browser, nctx, source, categoryDictionary) entry := model.SourceHealthEntry{ SourceID: source.Source.SourceID, AuthorityName: source.Source.AuthorityName, @@ -151,7 +151,7 @@ func (r Runner) runOnce(ctx context.Context, cfg config.Config) error { return err } -func (r Runner) fetchSource(ctx context.Context, fetcher fetch.Fetcher, nctx normalize.Context, source model.RegistrySource, categoryDictionary *dictionary.Store) ([]model.Alert, error) { +func (r Runner) fetchSource(ctx context.Context, fetcher fetch.Fetcher, browser *fetch.BrowserClient, nctx normalize.Context, source model.RegistrySource, categoryDictionary *dictionary.Store) ([]model.Alert, error) { switch source.Type { case "rss": return r.fetchRSS(ctx, fetcher, nctx, source) @@ -160,7 +160,7 @@ func (r Runner) fetchSource(ctx context.Context, fetcher fetch.Fetcher, nctx nor case "kev-json": return r.fetchKEV(ctx, fetcher, nctx, source) case "interpol-red-json", "interpol-yellow-json": - return r.fetchInterpol(ctx, fetcher, nctx, source) + return r.fetchInterpol(ctx, fetcher, browser, nctx, source) case "travelwarning-json": return r.fetchTravelWarningJSON(ctx, fetcher, nctx, source) case "travelwarning-atom": @@ -186,37 +186,10 @@ func (r Runner) fetchRSS(ctx context.Context, fetcher fetch.Fetcher, nctx normal } } limit := perSourceLimit(nctx.Config, source) - out := make([]model.Alert, 0, limit) - if nctx.Config.AlertLLMEnabled { - alertLLM := vet.NewClient(config.Config{ - HTTPTimeoutMS: nctx.Config.HTTPTimeoutMS, - VettingBaseURL: nctx.Config.VettingBaseURL, - VettingAPIKey: nctx.Config.VettingAPIKey, - VettingProvider: nctx.Config.VettingProvider, - VettingModel: nctx.Config.AlertLLMModel, - VettingTemperature: 0, - }) - classified, err := translate.BatchLLM(ctx, nctx.Config, alertLLM, source.Category, items) - if err != nil { - fmt.Fprintf(r.stderr, "WARN %s: alert llm failed: %v\n", source.Source.AuthorityName, err) - } else { - for _, classifiedItem := range classified { - if len(out) == limit { - break - } - if strings.TrimSpace(classifiedItem.Item.Title) == "" || strings.TrimSpace(classifiedItem.Item.Link) == "" { - continue - } - meta := source - meta.Category = firstNonEmpty(classifiedItem.Category, source.Category) - alert := normalize.RSSItem(nctx, meta, classifiedItem.Item) - if alert != nil { - out = append(out, *alert) - } - } - return out, nil - } + if len(items) > limit { + items = items[:limit] } + out := make([]model.Alert, 0, limit) for _, item := range items { if len(out) == limit { break @@ -241,6 +214,11 @@ func (r Runner) fetchHTML(ctx context.Context, fetcher fetch.Fetcher, nctx norma items = filterKeywords(items, source.IncludeKeywords, source.ExcludeKeywords) items = filterCategoryItems(items, source, categoryDictionary) limit := perSourceLimit(nctx.Config, source) + if nctx.Config.AlertLLMEnabled { + if llmLimit := nctx.Config.AlertLLMMaxItemsPerSource; llmLimit > 0 && llmLimit < limit { + limit = llmLimit + } + } if len(items) > limit { items = items[:limit] } @@ -312,14 +290,31 @@ func (r Runner) fetchKEV(ctx context.Context, fetcher fetch.Fetcher, nctx normal return out, nil } -func (r Runner) fetchInterpol(ctx context.Context, fetcher fetch.Fetcher, nctx normalize.Context, source model.RegistrySource) ([]model.Alert, error) { - body, err := fetcher.Text(ctx, source.FeedURL, source.FollowRedirects, "application/json") +func (r Runner) fetchInterpol(ctx context.Context, fetcher fetch.Fetcher, browser *fetch.BrowserClient, nctx normalize.Context, source model.RegistrySource) ([]model.Alert, error) { + var ( + body []byte + err error + ) + if browser != nil { + body, err = fetchInterpolViaBrowser(ctx, browser, source) + if err != nil { + fmt.Fprintf(r.stderr, "WARN %s: browser notice capture failed, falling back to direct fetch: %v\n", source.Source.AuthorityName, err) + } + } + if len(body) == 0 { + body, err = fetcher.Text(ctx, source.FeedURL, source.FollowRedirects, "application/json") + } if err != nil { return nil, err } + return parseInterpolNotices(nctx, source, body) +} + +func parseInterpolNotices(nctx normalize.Context, source model.RegistrySource, body []byte) ([]model.Alert, error) { var doc struct { Embedded struct { Notices []struct { + EntityID string `json:"entity_id"` Forename string `json:"forename"` Name string `json:"name"` PlaceOfBirth string `json:"place_of_birth"` @@ -359,15 +354,16 @@ func (r Runner) fetchInterpol(ctx context.Context, fetcher fetch.Fetcher, nctx n } } countryCode := "" - if len(notice.CountriesLikelyToVisit) > 0 { - countryCode = notice.CountriesLikelyToVisit[0] - } else if len(notice.Nationalities) > 0 { + if len(notice.Nationalities) > 0 { countryCode = notice.Nationalities[0] + } else if len(notice.CountriesLikelyToVisit) > 0 { + countryCode = notice.CountriesLikelyToVisit[0] } + noticeID := extractInterpolNoticeID(notice.EntityID, link) summary := strings.TrimSpace(notice.IssuingEntity + " " + notice.PlaceOfBirth) tags := append([]string{}, notice.Nationalities...) tags = append(tags, notice.CountriesLikelyToVisit...) - alert := normalize.InterpolAlert(nctx, source, title, link, countryCode, summary, tags) + alert := normalize.InterpolAlert(nctx, source, noticeID, title, link, countryCode, summary, tags) if alert != nil { out = append(out, *alert) } @@ -375,6 +371,53 @@ func (r Runner) fetchInterpol(ctx context.Context, fetcher fetch.Fetcher, nctx n return out, nil } +func fetchInterpolViaBrowser(ctx context.Context, browser *fetch.BrowserClient, source model.RegistrySource) ([]byte, error) { + pageURL, matchURL := interpolBrowserURLs(source.Type) + if pageURL == "" || matchURL == "" { + return nil, fmt.Errorf("no browser fallback for %s", source.Type) + } + bodies, err := browser.CaptureJSONResponses(ctx, pageURL, matchURL) + if err != nil { + return nil, err + } + for _, body := range bodies { + if len(body) > 0 { + return body, nil + } + } + return nil, fmt.Errorf("no interpol browser JSON bodies captured") +} + +func interpolBrowserURLs(sourceType string) (pageURL string, matchURL string) { + switch sourceType { + case "interpol-red-json": + return "https://www.interpol.int/How-we-work/Notices/Red-Notices/View-Red-Notices", "/notices/v1/red" + case "interpol-yellow-json": + return "https://www.interpol.int/How-we-work/Notices/Yellow-Notices/View-Yellow-Notices", "/notices/v1/yellow" + default: + return "", "" + } +} + +func extractInterpolNoticeID(entityID string, link string) string { + if id := strings.TrimSpace(entityID); id != "" { + return id + } + parsed, err := url.Parse(strings.TrimSpace(link)) + if err != nil { + return "" + } + if fragment := strings.TrimSpace(parsed.Fragment); fragment != "" { + return fragment + } + path := strings.Trim(parsed.Path, "/") + if path == "" { + return "" + } + parts := strings.Split(path, "/") + return strings.TrimSpace(parts[len(parts)-1]) +} + func (r Runner) fetchTravelWarningJSON(ctx context.Context, fetcher fetch.Fetcher, nctx normalize.Context, source model.RegistrySource) ([]model.Alert, error) { body, err := fetcher.Text(ctx, source.FeedURL, source.FollowRedirects, "application/json") if err != nil { diff --git a/internal/collector/run/run_test.go b/internal/collector/run/run_test.go index 16ab31a..dff2a9b 100644 --- a/internal/collector/run/run_test.go +++ b/internal/collector/run/run_test.go @@ -147,6 +147,18 @@ func TestBuildReplacementQueueFromPermanentFailures(t *testing.T) { } } +func TestExtractInterpolNoticeID(t *testing.T) { + if got := extractInterpolNoticeID("2026-17351", ""); got != "2026-17351" { + t.Fatalf("expected entity id to win, got %q", got) + } + if got := extractInterpolNoticeID("", "https://www.interpol.int/How-we-work/Notices/Yellow-Notices/View-Yellow-Notices#2026-17351"); got != "2026-17351" { + t.Fatalf("expected fragment id, got %q", got) + } + if got := extractInterpolNoticeID("", "https://ws-public.interpol.int/notices/v1/red/123"); got != "123" { + t.Fatalf("expected path id, got %q", got) + } +} + func TestFilterCategoryItemsDropsUnrelatedMissingPersonHTML(t *testing.T) { dict, err := dictionary.Load(filepath.Join("..", "..", "..", "registry", "category_dictionary.json")) if err != nil { diff --git a/internal/collector/translate/llm.go b/internal/collector/translate/llm.go index e89bd99..42f0df6 100644 --- a/internal/collector/translate/llm.go +++ b/internal/collector/translate/llm.go @@ -26,16 +26,32 @@ type AlertLLMResponse struct { CategoryID string `json:"category_id"` } +type alertBatchResponse struct { + Items []struct { + Index int `json:"index"` + Yes bool `json:"yes"` + Translation string `json:"translation"` + CategoryID string `json:"category_id"` + } `json:"items"` +} + type Completer interface { Complete(ctx context.Context, messages []vet.Message) (string, error) } func BatchLLM(ctx context.Context, cfg config.Config, client Completer, defaultCategory string, items []parse.FeedItem) ([]ClassifiedItem, error) { + if len(items) == 0 { + return nil, nil + } + results, err := classifyItems(ctx, client, cfg.AlertLLMModel, defaultCategory, items) + if err != nil { + return nil, err + } out := make([]ClassifiedItem, 0, len(items)) - for _, item := range items { - result, err := classifyItem(ctx, client, cfg.AlertLLMModel, defaultCategory, item) - if err != nil { - return nil, err + for index, item := range items { + result, ok := results[index] + if !ok { + continue } if !result.Yes { continue @@ -52,33 +68,40 @@ func BatchLLM(ctx context.Context, cfg config.Config, client Completer, defaultC return out, nil } -func classifyItem(ctx context.Context, client Completer, model string, defaultCategory string, item parse.FeedItem) (AlertLLMResponse, error) { +func classifyItems(ctx context.Context, client Completer, model string, defaultCategory string, items []parse.FeedItem) (map[int]AlertLLMResponse, error) { + batch := make([]map[string]any, 0, len(items)) + for index, item := range items { + batch = append(batch, map[string]any{ + "index": index, + "default_category": defaultCategory, + "title": strings.TrimSpace(item.Title), + "summary": strings.TrimSpace(item.Summary), + "link": strings.TrimSpace(item.Link), + "tags": item.Tags, + }) + } payload, err := json.MarshalIndent(map[string]any{ - "default_category": defaultCategory, - "title": strings.TrimSpace(item.Title), - "summary": strings.TrimSpace(item.Summary), - "link": strings.TrimSpace(item.Link), - "tags": item.Tags, + "items": batch, }, "", " ") if err != nil { - return AlertLLMResponse{}, fmt.Errorf("marshal alert llm input: %w", err) + return nil, fmt.Errorf("marshal alert llm input: %w", err) } content, err := client.Complete(ctx, []vet.Message{ { Role: "system", - Content: "You classify a public source alert item. Return strict JSON only with keys yes, translation, category_id. yes must be true only for intelligence-relevant alerts, not generic information/noise. translation must be a short English title. category_id must be one of the known category ids or the supplied default_category.", + Content: "You classify public source alert items. Return strict JSON only in the form {\"items\":[{\"index\":0,\"yes\":true,\"translation\":\"short english title\",\"category_id\":\"known_or_default\"}]}. yes must be true only for intelligence-relevant alerts, not generic information/noise. translation must be a short English title. category_id must be one of the known category ids or the supplied default_category.", }, { Role: "user", - Content: "Model: " + model + "\nEvaluate this item and return JSON only.\n\n" + string(payload), + Content: "Model: " + model + "\nEvaluate these items and return JSON only.\n\n" + string(payload), }, }) if err != nil { - return AlertLLMResponse{}, err + return nil, err } - return decodeAlertLLMResponse(content) + return decodeAlertBatchLLMResponse(content) } var alertJSONBlockRe = regexp.MustCompile(`(?s)\{.*\}`) @@ -97,6 +120,26 @@ func decodeAlertLLMResponse(content string) (AlertLLMResponse, error) { return out, nil } +func decodeAlertBatchLLMResponse(content string) (map[int]AlertLLMResponse, error) { + content = strings.TrimSpace(content) + if match := alertJSONBlockRe.FindString(content); match != "" { + content = match + } + var out alertBatchResponse + if err := json.Unmarshal([]byte(content), &out); err != nil { + return nil, fmt.Errorf("decode alert llm batch response: %w", err) + } + results := make(map[int]AlertLLMResponse, len(out.Items)) + for _, item := range out.Items { + results[item.Index] = AlertLLMResponse{ + Yes: item.Yes, + Translation: strings.TrimSpace(item.Translation), + CategoryID: strings.TrimSpace(item.CategoryID), + } + } + return results, nil +} + func firstNonEmpty(values ...string) string { for _, value := range values { value = strings.TrimSpace(value) diff --git a/internal/collector/translate/llm_test.go b/internal/collector/translate/llm_test.go index d8e5465..99860a5 100644 --- a/internal/collector/translate/llm_test.go +++ b/internal/collector/translate/llm_test.go @@ -35,7 +35,7 @@ func TestBatchLLMFiltersAndOverridesCategory(t *testing.T) { cfg := config.Default() cfg.AlertLLMModel = "gpt-test" items := []parse.FeedItem{{Title: "Titulo", Link: "https://example.test/a"}} - classified, err := BatchLLM(context.Background(), cfg, fakeCompleter{content: `{"yes":true,"translation":"Missing child in Madrid","category_id":"missing_person"}`}, "public_appeal", items) + classified, err := BatchLLM(context.Background(), cfg, fakeCompleter{content: `{"items":[{"index":0,"yes":true,"translation":"Missing child in Madrid","category_id":"missing_person"}]}`}, "public_appeal", items) if err != nil { t.Fatal(err) } @@ -50,7 +50,7 @@ func TestBatchLLMFiltersAndOverridesCategory(t *testing.T) { func TestBatchLLMDropsNoise(t *testing.T) { cfg := config.Default() items := []parse.FeedItem{{Title: "General update", Link: "https://example.test/a"}} - classified, err := BatchLLM(context.Background(), cfg, fakeCompleter{content: `{"yes":false,"translation":"","category_id":""}`}, "public_appeal", items) + classified, err := BatchLLM(context.Background(), cfg, fakeCompleter{content: `{"items":[{"index":0,"yes":false,"translation":"","category_id":""}]}`}, "public_appeal", items) if err != nil { t.Fatal(err) } @@ -58,3 +58,19 @@ func TestBatchLLMDropsNoise(t *testing.T) { t.Fatalf("expected no classified items, got %d", len(classified)) } } + +func TestDecodeAlertBatchLLMResponse(t *testing.T) { + got, err := decodeAlertBatchLLMResponse("```json\n{\"items\":[{\"index\":0,\"yes\":true,\"translation\":\"Wanted suspect in Berlin\",\"category_id\":\"wanted_suspect\"},{\"index\":1,\"yes\":false,\"translation\":\"\",\"category_id\":\"\"}]}\n```") + if err != nil { + t.Fatal(err) + } + if len(got) != 2 { + t.Fatalf("expected 2 batch responses, got %d", len(got)) + } + if !got[0].Yes || got[0].CategoryID != "wanted_suspect" { + t.Fatalf("unexpected first batch response %#v", got[0]) + } + if got[1].Yes { + t.Fatalf("expected second batch response to be negative, got %#v", got[1]) + } +} diff --git a/internal/sourcedb/db.go b/internal/sourcedb/db.go index 0c7211c..e610d82 100644 --- a/internal/sourcedb/db.go +++ b/internal/sourcedb/db.go @@ -13,6 +13,7 @@ import ( "path/filepath" "sort" "strings" + "sync" _ "modernc.org/sqlite" @@ -22,6 +23,8 @@ import ( //go:embed schema.sql var schemaSQL string +var initMu sync.Mutex + type DB struct { sql *sql.DB } @@ -46,6 +49,10 @@ func Open(path string) (*DB, error) { if err != nil { return nil, fmt.Errorf("open sqlite source DB: %w", err) } + if _, err := db.Exec(`PRAGMA busy_timeout = 5000`); err != nil { + db.Close() + return nil, fmt.Errorf("set sqlite busy_timeout: %w", err) + } return &DB{sql: db}, nil } @@ -57,6 +64,9 @@ func (db *DB) Close() error { } func (db *DB) Init(ctx context.Context) error { + initMu.Lock() + defer initMu.Unlock() + if _, err := db.sql.ExecContext(ctx, schemaSQL); err != nil { return fmt.Errorf("init source DB schema: %w", err) } @@ -228,6 +238,9 @@ func (db *DB) UpsertRegistrySources(ctx context.Context, sources []model.Registr } func (db *DB) LoadActiveSources(ctx context.Context) ([]model.RegistrySource, error) { + if err := db.Init(ctx); err != nil { + return nil, err + } rows, err := db.sql.QueryContext(ctx, ` SELECT s.id, diff --git a/internal/sourcedb/db_test.go b/internal/sourcedb/db_test.go index 3b7a149..9477d32 100644 --- a/internal/sourcedb/db_test.go +++ b/internal/sourcedb/db_test.go @@ -51,6 +51,118 @@ func TestImportAndExportRegistry(t *testing.T) { } } +func TestLoadActiveSourcesAutoMigratesOlderDatabase(t *testing.T) { + dir := t.TempDir() + dbPath := filepath.Join(dir, "sources.db") + + db, err := Open(dbPath) + if err != nil { + t.Fatal(err) + } + defer db.Close() + + // Simulate an older DB that predates the hygiene columns added later. + for _, stmt := range []string{ + `CREATE TABLE agencies ( + id TEXT PRIMARY KEY, + authority_name TEXT NOT NULL, + country TEXT NOT NULL DEFAULT '', + country_code TEXT NOT NULL DEFAULT '', + region TEXT NOT NULL DEFAULT '', + authority_type TEXT NOT NULL DEFAULT '', + base_url TEXT NOT NULL DEFAULT '', + scope TEXT NOT NULL DEFAULT 'national', + jurisdiction_name TEXT NOT NULL DEFAULT '', + parent_agency_id TEXT NOT NULL DEFAULT '', + is_curated INTEGER NOT NULL DEFAULT 0, + is_high_value INTEGER NOT NULL DEFAULT 0, + language_code TEXT NOT NULL DEFAULT '' + )`, + `CREATE TABLE sources ( + id TEXT PRIMARY KEY, + agency_id TEXT NOT NULL, + type TEXT NOT NULL, + fetch_mode TEXT NOT NULL DEFAULT '', + status TEXT NOT NULL DEFAULT 'active', + follow_redirects INTEGER NOT NULL DEFAULT 1, + feed_url TEXT NOT NULL, + feed_urls_json TEXT NOT NULL DEFAULT '[]', + category TEXT NOT NULL DEFAULT '', + region_tag TEXT NOT NULL DEFAULT '', + lat REAL NOT NULL DEFAULT 0, + lng REAL NOT NULL DEFAULT 0, + max_items INTEGER NOT NULL DEFAULT 20, + include_keywords_json TEXT NOT NULL DEFAULT '[]', + exclude_keywords_json TEXT NOT NULL DEFAULT '[]', + reporting_label TEXT NOT NULL DEFAULT '', + reporting_url TEXT NOT NULL DEFAULT '', + reporting_phone TEXT NOT NULL DEFAULT '', + reporting_notes TEXT NOT NULL DEFAULT '', + last_http_status INTEGER NOT NULL DEFAULT 0, + last_ok_at TEXT NOT NULL DEFAULT '', + last_error TEXT NOT NULL DEFAULT '', + last_error_class TEXT NOT NULL DEFAULT '', + created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP + )`, + `CREATE TABLE source_categories ( + source_id TEXT NOT NULL, + category TEXT NOT NULL, + PRIMARY KEY (source_id, category) + )`, + `CREATE TABLE source_candidates ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + discovered_url TEXT NOT NULL, + discovered_via TEXT NOT NULL DEFAULT '', + status TEXT NOT NULL DEFAULT 'candidate', + language_code TEXT NOT NULL DEFAULT '', + category TEXT NOT NULL DEFAULT '', + authority_type TEXT NOT NULL DEFAULT '', + country TEXT NOT NULL DEFAULT '', + country_code TEXT NOT NULL DEFAULT '', + notes TEXT NOT NULL DEFAULT '', + checked_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, + UNIQUE(discovered_url) + )`, + `CREATE TABLE agencies_fts ( + agency_id TEXT NOT NULL, + name TEXT NOT NULL, + aliases TEXT NOT NULL DEFAULT '' + )`, + `CREATE TABLE agency_category_coverage ( + agency_id TEXT NOT NULL, + category TEXT NOT NULL, + PRIMARY KEY (agency_id, category) + )`, + } { + if _, err := db.sql.ExecContext(context.Background(), stmt); err != nil { + t.Fatalf("seed old schema: %v", err) + } + } + + if _, err := db.sql.ExecContext(context.Background(), ` +INSERT INTO agencies (id, authority_name, country, country_code, region, authority_type, base_url, scope) +VALUES ('agency-one', 'Agency One', 'France', 'FR', 'Europe', 'cert', 'https://one.example', 'national')`); err != nil { + t.Fatal(err) + } + if _, err := db.sql.ExecContext(context.Background(), ` +INSERT INTO sources (id, agency_id, type, status, feed_url, category) +VALUES ('agency-one-feed', 'agency-one', 'rss', 'active', 'https://one.example/feed', 'cyber_advisory')`); err != nil { + t.Fatal(err) + } + + sources, err := db.LoadActiveSources(context.Background()) + if err != nil { + t.Fatal(err) + } + if len(sources) != 1 { + t.Fatalf("expected 1 active source after auto-migration, got %d", len(sources)) + } + if sources[0].PromotionStatus != "active" { + t.Fatalf("expected promotion_status backfill to active, got %q", sources[0].PromotionStatus) + } +} + func TestDeactivateSourcesRemovesThemFromActiveLoad(t *testing.T) { dir := t.TempDir() registryPath := filepath.Join(dir, "registry.json") diff --git a/registry/curated_agencies.seed.json b/registry/curated_agencies.seed.json index 8e57b4f..83cdc5e 100644 --- a/registry/curated_agencies.seed.json +++ b/registry/curated_agencies.seed.json @@ -1,6 +1,7 @@ [ { - "type": "rss", + "type": "interpol-red-json", + "fetch_mode": "browser", "source": { "source_id": "interpol-notices", "authority_name": "INTERPOL Notices", @@ -14,7 +15,7 @@ "is_high_value": true, "language_code": "en" }, - "feed_url": "https://www.interpol.int/How-we-work/Notices/View-Red-Notices", + "feed_url": "https://ws-public.interpol.int/notices/v1/red?page=1&resultPerPage=160", "category": "wanted_suspect", "region_tag": "INT", "lat": 45.764, @@ -25,7 +26,8 @@ } }, { - "type": "rss", + "type": "interpol-yellow-json", + "fetch_mode": "browser", "source": { "source_id": "interpol-missing", "authority_name": "INTERPOL Missing Persons", @@ -41,7 +43,7 @@ "is_high_value": true, "language_code": "en" }, - "feed_url": "https://www.interpol.int/How-we-work/Notices/View-Yellow-Notices", + "feed_url": "https://ws-public.interpol.int/notices/v1/yellow?page=1&resultPerPage=160", "category": "missing_person", "region_tag": "INT", "lat": 45.764, From f136f607d1a0c9431f285f2b335cf4a0fbb0e059 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 17:08:46 +0100 Subject: [PATCH 04/58] chore(ci): remove alerts refresh workflow --- .github/workflows/alerts-feed.yml | 53 ------------------------------- 1 file changed, 53 deletions(-) delete mode 100644 .github/workflows/alerts-feed.yml diff --git a/.github/workflows/alerts-feed.yml b/.github/workflows/alerts-feed.yml deleted file mode 100644 index c3dbf3c..0000000 --- a/.github/workflows/alerts-feed.yml +++ /dev/null @@ -1,53 +0,0 @@ -name: Update alerts feed - -on: - schedule: - - cron: "*/15 * * * *" - workflow_dispatch: {} - -concurrency: - group: alerts-feed - cancel-in-progress: true - -permissions: - contents: write - -jobs: - refresh: - name: refresh - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version-file: go.mod - cache: true - - - name: Fetch alerts with Go collector - run: go run ./cmd/euosint-collector - env: - MAX_PER_SOURCE: "20" - OUTPUT_PATH: "public/alerts.json" - FILTERED_OUTPUT_PATH: "public/alerts-filtered.json" - STATE_OUTPUT_PATH: "public/alerts-state.json" - SOURCE_HEALTH_OUTPUT_PATH: "public/source-health.json" - MISSING_PERSON_RELEVANCE_THRESHOLD: "0" - FAIL_ON_CRITICAL_SOURCE_GAP: "0" - CRITICAL_SOURCE_PREFIXES: "interpol-red,interpol-yellow" - - - name: Commit updates - run: | - if git diff --quiet -- public/alerts.json public/alerts-filtered.json public/alerts-state.json public/source-health.json; then - echo "No changes" - exit 0 - fi - git config user.name "euosint-bot" - git config user.email "euosint-bot@users.noreply.github.com" - git add public/alerts.json public/alerts-filtered.json public/alerts-state.json public/source-health.json - git commit -m "chore: update alerts feed" - git push From 2097b5fd7b369b2279cffaa71610d0817b8ff2cf Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 17:08:51 +0100 Subject: [PATCH 05/58] feat(discovery): improve feed search and wikidata hygiene --- .env.example | 4 + docs/source-vetting.md | 16 ++- internal/collector/app/app.go | 4 + internal/collector/config/config.go | 12 ++ internal/collector/discover/discover.go | 81 ++++++++++-- internal/collector/discover/discover_test.go | 86 +++++++++++- internal/collector/discover/first.go | 38 +++++- internal/collector/discover/http.go | 77 +++++++++++ internal/collector/discover/humanitarian.go | 130 +++++++++++-------- internal/collector/discover/police.go | 5 +- internal/collector/discover/search_llm.go | 43 +++++- internal/collector/fetch/client.go | 10 ++ 12 files changed, 432 insertions(+), 74 deletions(-) diff --git a/.env.example b/.env.example index 9868d6b..441ba6c 100644 --- a/.env.example +++ b/.env.example @@ -4,6 +4,9 @@ EUOSINT_SITE_ADDRESS=:80 EUOSINT_HTTP_PORT=8080 EUOSINT_HTTPS_PORT=8443 +HTTP_TIMEOUT_MS=60000 +BROWSER_ENABLED=true +BROWSER_TIMEOUT_MS=60000 # Candidate crawler intake and dead-letter queue. CANDIDATE_QUEUE_PATH=registry/source_candidates.json @@ -24,3 +27,4 @@ SOURCE_VETTING_MAX_SAMPLE_ITEMS=6 # Alert-level LLM gate: yes/no + English translation + category id. ALERT_LLM_ENABLED=false ALERT_LLM_MODEL=grok-4-1-fast +ALERT_LLM_MAX_ITEMS_PER_SOURCE=4 diff --git a/docs/source-vetting.md b/docs/source-vetting.md index c964764..e1fe27b 100644 --- a/docs/source-vetting.md +++ b/docs/source-vetting.md @@ -76,6 +76,7 @@ Bad pattern: SEARCH_DISCOVERY_ENABLED=true SEARCH_DISCOVERY_MAX_TARGETS=4 SEARCH_DISCOVERY_MAX_URLS_PER_TARGET=3 +HTTP_TIMEOUT_MS=60000 SOURCE_VETTING_ENABLED=true SOURCE_VETTING_PROVIDER=xai SOURCE_VETTING_BASE_URL=https://api.x.ai/v1 @@ -85,6 +86,7 @@ SOURCE_VETTING_TEMPERATURE=0 SOURCE_VETTING_MAX_SAMPLE_ITEMS=6 ALERT_LLM_ENABLED=true ALERT_LLM_MODEL=grok-4-1-fast +ALERT_LLM_MAX_ITEMS_PER_SOURCE=4 ``` Put the real API key only in your local `.env`. Do not commit it. @@ -198,9 +200,9 @@ The live watcher only loads `promotion_status = active`. ## Alert-Level LLM Gate -You can also enable an item-level LLM gate for RSS and HTML-list items. +You can also enable an item-level LLM gate for ambiguous `html-list` sources. -When enabled, each candidate alert item is sent to the same OpenAI-compatible endpoint with a short prompt that must return strict JSON: +When enabled, each candidate HTML item is sent to the same OpenAI-compatible endpoint with a short prompt that must return strict JSON: - `yes`: whether the item is intelligence-relevant or just noise - `translation`: a short English title @@ -209,15 +211,25 @@ When enabled, each candidate alert item is sent to the same OpenAI-compatible en If `yes = false`, the collector drops the item. If `yes = true`, the collector uses the English title and category override during normalization. +RSS, Atom, and structured API sources stay on the deterministic collector path so the live watcher does not stall behind LLM latency. + Example: ```dotenv ALERT_LLM_ENABLED=true ALERT_LLM_MODEL=grok-4-1-fast +ALERT_LLM_MAX_ITEMS_PER_SOURCE=4 ``` This uses the same provider/base URL/API key as source vetting. +For xAI and similar reasoning-heavy models, keep `ALERT_LLM_MAX_ITEMS_PER_SOURCE` low and raise `HTTP_TIMEOUT_MS` above the default collector timeout. A practical starting point is: + +```dotenv +HTTP_TIMEOUT_MS=60000 +ALERT_LLM_MAX_ITEMS_PER_SOURCE=4 +``` + The same principle applies here: if your configured model supports search, use it to return a strict, short yes/no decision, a short English title, and a category id. Keep prompts short and outputs structured to avoid wasting tokens. Equivalent xAI request shape: diff --git a/internal/collector/app/app.go b/internal/collector/app/app.go index 73fc90f..038f7ea 100644 --- a/internal/collector/app/app.go +++ b/internal/collector/app/app.go @@ -44,6 +44,9 @@ func Run(ctx context.Context, args []string, stdout io.Writer, stderr io.Writer) fs.BoolVar(&cfg.SearchDiscoveryEnabled, "search-discovery", cfg.SearchDiscoveryEnabled, "Use the configured OpenAI-compatible model as a token-safe candidate URL discovery accelerator") fs.IntVar(&cfg.SearchDiscoveryMaxTargets, "search-discovery-max-targets", cfg.SearchDiscoveryMaxTargets, "Maximum number of search-discovery targets per run") fs.IntVar(&cfg.SearchDiscoveryMaxURLsPerTarget, "search-discovery-max-urls", cfg.SearchDiscoveryMaxURLsPerTarget, "Maximum number of URLs requested from the model per search target") + fs.StringVar(&cfg.WikimediaUserAgent, "wikimedia-user-agent", cfg.WikimediaUserAgent, "Identifying bot User-Agent for Wikimedia/Wikidata requests") + fs.StringVar(&cfg.WikidataCachePath, "wikidata-cache-path", cfg.WikidataCachePath, "Directory for cached Wikidata discovery responses") + fs.IntVar(&cfg.WikidataCacheTTLHours, "wikidata-cache-ttl-hours", cfg.WikidataCacheTTLHours, "How long to reuse cached Wikidata discovery responses") fs.BoolVar(&cfg.VettingEnabled, "source-vetting", cfg.VettingEnabled, "Enable LLM-assisted source vetting and promotion for discovered candidates") fs.StringVar(&cfg.VettingProvider, "source-vetting-provider", cfg.VettingProvider, "LLM provider label for docs/logging (openai, mistral, xai, claude, gemini, vllm, ollama)") fs.StringVar(&cfg.VettingBaseURL, "source-vetting-base-url", cfg.VettingBaseURL, "OpenAI-compatible base URL for source vetting") @@ -53,6 +56,7 @@ func Run(ctx context.Context, args []string, stdout io.Writer, stderr io.Writer) fs.IntVar(&cfg.VettingMaxSampleItems, "source-vetting-max-samples", cfg.VettingMaxSampleItems, "Maximum sample items fetched per discovered source for vetting") fs.BoolVar(&cfg.AlertLLMEnabled, "alert-llm", cfg.AlertLLMEnabled, "Enable LLM alert translation and yes/no category gating") fs.StringVar(&cfg.AlertLLMModel, "alert-llm-model", cfg.AlertLLMModel, "Model name for LLM alert translation/gating") + fs.IntVar(&cfg.AlertLLMMaxItemsPerSource, "alert-llm-max-items", cfg.AlertLLMMaxItemsPerSource, "Maximum number of alert items per source sent to the alert LLM in one collector pass") fs.StringVar(&cfg.ReplacementQueuePath, "replacement-queue", cfg.ReplacementQueuePath, "Path for the dead-source DLQ JSON file") fs.StringVar(&cfg.SourceDBPath, "source-db", cfg.SourceDBPath, "Path to the SQLite source database") fs.BoolVar(&cfg.SourceDBInit, "source-db-init", cfg.SourceDBInit, "Initialize the SQLite source database schema") diff --git a/internal/collector/config/config.go b/internal/collector/config/config.go index 494f62c..b8c11d3 100644 --- a/internal/collector/config/config.go +++ b/internal/collector/config/config.go @@ -41,6 +41,7 @@ type Config struct { HTTPTimeoutMS int MaxResponseBodyBytes int64 UserAgent string + WikimediaUserAgent string TranslateEnabled bool BrowserEnabled bool BrowserTimeoutMS int @@ -52,6 +53,8 @@ type Config struct { SearchDiscoveryEnabled bool SearchDiscoveryMaxTargets int SearchDiscoveryMaxURLsPerTarget int + WikidataCachePath string + WikidataCacheTTLHours int VettingEnabled bool VettingProvider string VettingBaseURL string @@ -61,6 +64,7 @@ type Config struct { VettingMaxSampleItems int AlertLLMEnabled bool AlertLLMModel string + AlertLLMMaxItemsPerSource int CategoryDictionaryPath string ReplacementQueuePath string SourceDBPath string @@ -90,6 +94,7 @@ func Default() Config { HTTPTimeoutMS: defaultTimeoutMS, MaxResponseBodyBytes: defaultMaxBodyBytes, UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36", + WikimediaUserAgent: "EUOSINTBot/1.0 (https://www.scalytics.io; ops@scalytics.io) WDQS discovery", TranslateEnabled: true, BrowserEnabled: false, BrowserTimeoutMS: 30000, @@ -101,6 +106,8 @@ func Default() Config { SearchDiscoveryEnabled: false, SearchDiscoveryMaxTargets: 4, SearchDiscoveryMaxURLsPerTarget: 3, + WikidataCachePath: "registry/wikidata_cache", + WikidataCacheTTLHours: 24, VettingEnabled: false, VettingProvider: "openai-compatible", VettingBaseURL: "https://api.openai.com/v1", @@ -109,6 +116,7 @@ func Default() Config { VettingMaxSampleItems: 6, AlertLLMEnabled: false, AlertLLMModel: "gpt-4.1-mini", + AlertLLMMaxItemsPerSource: 4, CategoryDictionaryPath: "registry/category_dictionary.json", ReplacementQueuePath: "registry/source_dead_letter.json", SourceDBPath: "registry/sources.db", @@ -139,6 +147,7 @@ func FromEnv() Config { cfg.HTTPTimeoutMS = envInt("HTTP_TIMEOUT_MS", cfg.HTTPTimeoutMS) cfg.MaxResponseBodyBytes = int64(envInt("MAX_RESPONSE_BODY_BYTES", int(cfg.MaxResponseBodyBytes))) cfg.UserAgent = envString("USER_AGENT", cfg.UserAgent) + cfg.WikimediaUserAgent = envString("WIKIMEDIA_USER_AGENT", cfg.WikimediaUserAgent) cfg.TranslateEnabled = envBool("TRANSLATE_ENABLED", cfg.TranslateEnabled) cfg.BrowserEnabled = envBool("BROWSER_ENABLED", cfg.BrowserEnabled) cfg.BrowserTimeoutMS = envInt("BROWSER_TIMEOUT_MS", cfg.BrowserTimeoutMS) @@ -150,6 +159,8 @@ func FromEnv() Config { cfg.SearchDiscoveryEnabled = envBool("SEARCH_DISCOVERY_ENABLED", cfg.SearchDiscoveryEnabled) cfg.SearchDiscoveryMaxTargets = envInt("SEARCH_DISCOVERY_MAX_TARGETS", cfg.SearchDiscoveryMaxTargets) cfg.SearchDiscoveryMaxURLsPerTarget = envInt("SEARCH_DISCOVERY_MAX_URLS_PER_TARGET", cfg.SearchDiscoveryMaxURLsPerTarget) + cfg.WikidataCachePath = envString("WIKIDATA_CACHE_PATH", cfg.WikidataCachePath) + cfg.WikidataCacheTTLHours = envInt("WIKIDATA_CACHE_TTL_HOURS", cfg.WikidataCacheTTLHours) cfg.VettingEnabled = envBool("SOURCE_VETTING_ENABLED", cfg.VettingEnabled) cfg.VettingProvider = envString("SOURCE_VETTING_PROVIDER", cfg.VettingProvider) cfg.VettingBaseURL = envString("SOURCE_VETTING_BASE_URL", cfg.VettingBaseURL) @@ -159,6 +170,7 @@ func FromEnv() Config { cfg.VettingMaxSampleItems = envInt("SOURCE_VETTING_MAX_SAMPLE_ITEMS", cfg.VettingMaxSampleItems) cfg.AlertLLMEnabled = envBool("ALERT_LLM_ENABLED", cfg.AlertLLMEnabled) cfg.AlertLLMModel = envString("ALERT_LLM_MODEL", cfg.AlertLLMModel) + cfg.AlertLLMMaxItemsPerSource = envInt("ALERT_LLM_MAX_ITEMS_PER_SOURCE", cfg.AlertLLMMaxItemsPerSource) cfg.CategoryDictionaryPath = envString("CATEGORY_DICTIONARY_PATH", cfg.CategoryDictionaryPath) cfg.ReplacementQueuePath = envString("REPLACEMENT_QUEUE_PATH", cfg.ReplacementQueuePath) cfg.SourceDBPath = envString("SOURCE_DB_PATH", cfg.SourceDBPath) diff --git a/internal/collector/discover/discover.go b/internal/collector/discover/discover.go index 33fc4ce..014fada 100644 --- a/internal/collector/discover/discover.go +++ b/internal/collector/discover/discover.go @@ -71,7 +71,7 @@ func Run(ctx context.Context, cfg config.Config, stdout io.Writer, stderr io.Wri var discovered []DiscoveredSource dead := loadDeadLetterQueue(cfg.ReplacementQueuePath) fmt.Fprintf(stderr, "Dead-letter queue: %d sources will be skipped\n", len(dead)) - seededCandidates, err := generateAutonomousCandidates(ctx, cfg, client, searchClient, stderr) + seededCandidates, err := generateAutonomousCandidates(ctx, cfg, client, searchClient, dead, stderr) if err != nil { fmt.Fprintf(stderr, "WARN autonomous candidate discovery failed: %v\n", err) } @@ -180,13 +180,18 @@ func Run(ctx context.Context, cfg config.Config, stdout io.Writer, stderr io.Wri return nil } -func generateAutonomousCandidates(ctx context.Context, cfg config.Config, client *fetch.Client, searchClient searchCompleter, stderr io.Writer) ([]model.SourceCandidate, error) { +func generateAutonomousCandidates(ctx context.Context, cfg config.Config, client *fetch.Client, searchClient searchCompleter, dead []model.SourceReplacementCandidate, stderr io.Writer) ([]model.SourceCandidate, error) { candidates := make([]model.SourceCandidate, 0) var failures []string + var slowSkips []string teams, err := FetchFIRSTTeams(ctx, client) if err != nil { - failures = append(failures, fmt.Sprintf("FIRST.org: %v", err)) + if isDiscoveryTimeout(err) { + slowSkips = append(slowSkips, "FIRST.org") + } else { + failures = append(failures, fmt.Sprintf("FIRST.org: %v", err)) + } } else { fmt.Fprintf(stderr, "FIRST.org: fetched %d teams for candidate seeding\n", len(teams)) for _, team := range teams { @@ -202,9 +207,13 @@ func generateAutonomousCandidates(ctx context.Context, cfg config.Config, client } } - agencies, err := FetchPoliceAgencies(ctx, client) + agencies, err := FetchPoliceAgencies(ctx, cfg, client) if err != nil { - failures = append(failures, fmt.Sprintf("Wikidata police: %v", err)) + if isDiscoveryTimeout(err) { + slowSkips = append(slowSkips, "Wikidata police") + } else { + failures = append(failures, fmt.Sprintf("Wikidata police: %v", err)) + } } else { fmt.Fprintf(stderr, "Wikidata: fetched %d police/law-enforcement agencies for candidate seeding\n", len(agencies)) for _, agency := range agencies { @@ -224,9 +233,13 @@ func generateAutonomousCandidates(ctx context.Context, cfg config.Config, client } } - humOrgs, err := FetchHumanitarianOrgs(ctx, client) + humOrgs, err := FetchHumanitarianOrgs(ctx, cfg, client) if err != nil { - failures = append(failures, fmt.Sprintf("Wikidata humanitarian: %v", err)) + if isDiscoveryTimeout(err) { + slowSkips = append(slowSkips, "Wikidata humanitarian") + } else { + failures = append(failures, fmt.Sprintf("Wikidata humanitarian: %v", err)) + } } else { fmt.Fprintf(stderr, "Wikidata: fetched %d humanitarian/emergency orgs for candidate seeding\n", len(humOrgs)) for _, org := range humOrgs { @@ -249,7 +262,16 @@ func generateAutonomousCandidates(ctx context.Context, cfg config.Config, client if len(failures) > 0 { fmt.Fprintf(stderr, "WARN structured discovery partially failed: %s\n", strings.Join(failures, " | ")) } - llmCandidates, err := llmSearchCandidates(ctx, cfg, searchClient, candidates) + if len(slowSkips) > 0 { + fmt.Fprintf(stderr, "Structured discovery skipped slow providers: %s\n", strings.Join(slowSkips, ", ")) + } + searchSeeds := append([]model.SourceCandidate{}, candidates...) + replacementTargets := buildReplacementSearchTargets(dead) + if len(replacementTargets) > 0 { + fmt.Fprintf(stderr, "Replacement search targets: %d dead-source metadata entries queued for feed search\n", len(replacementTargets)) + searchSeeds = append(searchSeeds, replacementTargets...) + } + llmCandidates, err := llmSearchCandidates(ctx, cfg, searchClient, searchSeeds) if err != nil { failures = append(failures, fmt.Sprintf("llm-search: %v", err)) } else if len(llmCandidates) > 0 { @@ -262,6 +284,49 @@ func generateAutonomousCandidates(ctx context.Context, cfg config.Config, client return candidates, nil } +func isDiscoveryTimeout(err error) bool { + if err == nil { + return false + } + msg := strings.ToLower(err.Error()) + return strings.Contains(msg, "timeout") || + strings.Contains(msg, "deadline exceeded") || + strings.Contains(msg, "request canceled") +} + +func buildReplacementSearchTargets(dead []model.SourceReplacementCandidate) []model.SourceCandidate { + out := make([]model.SourceCandidate, 0, len(dead)) + seen := map[string]struct{}{} + for _, entry := range dead { + target := model.SourceCandidate{ + AuthorityName: strings.TrimSpace(entry.AuthorityName), + AuthorityType: strings.TrimSpace(entry.AuthorityType), + Category: strings.TrimSpace(entry.Category), + Country: strings.TrimSpace(entry.Country), + CountryCode: strings.ToUpper(strings.TrimSpace(entry.CountryCode)), + Region: strings.TrimSpace(entry.Region), + BaseURL: strings.TrimSpace(entry.BaseURL), + Notes: "replacement-search: dead-source metadata", + } + if target.BaseURL == "" { + target.BaseURL = strings.TrimSpace(entry.FeedURL) + } + if !passesDiscoveryHygiene(target.AuthorityName, firstNonEmpty(target.BaseURL, target.URL), target.AuthorityType) { + continue + } + key := strings.ToLower(target.AuthorityName) + "|" + target.CountryCode + "|" + strings.ToLower(target.Category) + "|" + normalizeURL(firstNonEmpty(target.BaseURL, target.URL)) + if key == "|||" { + continue + } + if _, ok := seen[key]; ok { + continue + } + seen[key] = struct{}{} + out = append(out, target) + } + return out +} + func mergeCandidates(existingQueue []model.SourceCandidate, discovered []model.SourceCandidate, active map[string]struct{}, dead []model.SourceReplacementCandidate) []model.SourceCandidate { out := make([]model.SourceCandidate, 0, len(existingQueue)+len(discovered)) seen := map[string]struct{}{} diff --git a/internal/collector/discover/discover_test.go b/internal/collector/discover/discover_test.go index c1f8ae5..8806dcd 100644 --- a/internal/collector/discover/discover_test.go +++ b/internal/collector/discover/discover_test.go @@ -5,6 +5,8 @@ package discover import ( "context" + "encoding/json" + "errors" "os" "path/filepath" "strings" @@ -177,7 +179,7 @@ func TestLLMSearchCandidatesReturnsTokenSafeCandidates(t *testing.T) { cfg.VettingProvider = "xai" got, err := llmSearchCandidates(context.Background(), cfg, stubSearchCompleter{ - content: `{"urls":[{"url":"https://www.europol.europa.eu/cms/api/rss/news","reason":"official rss"},{"url":"https://www.europol.europa.eu/newsroom","reason":"official newsroom"},{"url":"not-a-url","reason":"ignore"}]}`, + content: `{"urls":[{"url":"https://www.europol.europa.eu/cms/api/rss/news","reason":"official rss"},{"url":"https://www.europol.europa.eu/feed.xml","reason":"official atom"},{"url":"https://www.europol.europa.eu/newsroom","reason":"ignore non-feed"}]}`, }, []model.SourceCandidate{ {AuthorityName: "Europol", URL: "https://www.europol.europa.eu", AuthorityType: "police", Category: "public_appeal", Country: "Netherlands", CountryCode: "NL"}, }) @@ -194,3 +196,85 @@ func TestLLMSearchCandidatesReturnsTokenSafeCandidates(t *testing.T) { t.Fatalf("expected metadata to be preserved, got %#v", got[0]) } } + +func TestFirstWebsiteFieldAcceptsStringOrArray(t *testing.T) { + var got struct { + Website firstWebsiteField `json:"website"` + } + if err := json.Unmarshal([]byte(`{"website":"https://example.test"}`), &got); err != nil { + t.Fatalf("unmarshal string website: %v", err) + } + if string(got.Website) != "https://example.test" { + t.Fatalf("unexpected string website %q", got.Website) + } + if err := json.Unmarshal([]byte(`{"website":["","https://array.example/feed"]}`), &got); err != nil { + t.Fatalf("unmarshal array website: %v", err) + } + if string(got.Website) != "https://array.example/feed" { + t.Fatalf("unexpected array website %q", got.Website) + } +} + +func TestBuildReplacementSearchTargetsUsesMetadataNotDeadURL(t *testing.T) { + targets := buildReplacementSearchTargets([]model.SourceReplacementCandidate{ + { + SourceID: "bka", + AuthorityName: "Bundeskriminalamt", + FeedURL: "https://dead.example/rss", + BaseURL: "https://www.bka.de", + Country: "Germany", + CountryCode: "DE", + Region: "Europe", + AuthorityType: "police", + Category: "wanted_suspect", + }, + }) + if len(targets) != 1 { + t.Fatalf("expected 1 replacement search target, got %d", len(targets)) + } + if targets[0].BaseURL != "https://www.bka.de" { + t.Fatalf("expected base URL to be used for replacement search, got %#v", targets[0]) + } + if targets[0].URL != "" { + t.Fatalf("expected dead feed URL not to be reintroduced as direct candidate, got %#v", targets[0]) + } + if !strings.HasPrefix(targets[0].Notes, "replacement-search:") { + t.Fatalf("expected replacement-search note, got %#v", targets[0]) + } +} + +func TestIsDiscoveryTimeout(t *testing.T) { + tests := []struct { + name string + err error + want bool + }{ + {name: "deadline", err: context.DeadlineExceeded, want: true}, + {name: "timeout text", err: errors.New("fetch failed: context deadline exceeded"), want: true}, + {name: "request canceled", err: errors.New("request canceled while awaiting headers"), want: true}, + {name: "parse failure", err: errors.New("json parse error"), want: false}, + } + for _, tt := range tests { + if got := isDiscoveryTimeout(tt.err); got != tt.want { + t.Fatalf("%s: got %v want %v", tt.name, got, tt.want) + } + } +} + +func TestWikidataCacheRoundTrip(t *testing.T) { + cfg := config.Default() + cfg.WikidataCachePath = t.TempDir() + cfg.WikidataCacheTTLHours = 24 + + url := "https://query.wikidata.org/sparql?format=json&query=test" + want := []byte(`{"results":{"bindings":[]}}`) + writeWikidataCache(cfg, url, want) + + got, ok := readWikidataCache(cfg, url) + if !ok { + t.Fatal("expected cached wikidata response to be readable") + } + if string(got) != string(want) { + t.Fatalf("unexpected cache body %q", string(got)) + } +} diff --git a/internal/collector/discover/first.go b/internal/collector/discover/first.go index a0cde49..c274dea 100644 --- a/internal/collector/discover/first.go +++ b/internal/collector/discover/first.go @@ -22,6 +22,34 @@ type FIRSTTeam struct { Website string `json:"website"` } +type firstWebsiteField string + +func (f *firstWebsiteField) UnmarshalJSON(data []byte) error { + data = []byte(strings.TrimSpace(string(data))) + if string(data) == "null" || len(data) == 0 { + *f = "" + return nil + } + var single string + if err := json.Unmarshal(data, &single); err == nil { + *f = firstWebsiteField(strings.TrimSpace(single)) + return nil + } + var many []string + if err := json.Unmarshal(data, &many); err == nil { + for _, entry := range many { + entry = strings.TrimSpace(entry) + if entry != "" { + *f = firstWebsiteField(entry) + return nil + } + } + *f = "" + return nil + } + return fmt.Errorf("unsupported FIRST website field: %s", string(data)) +} + // FetchFIRSTTeams fetches all CSIRT teams from the FIRST.org API, // paginating through all results. Returns teams that have a non-empty // website URL. @@ -40,10 +68,10 @@ func FetchFIRSTTeams(ctx context.Context, client *fetch.Client) ([]FIRSTTeam, er var resp struct { Data []struct { - ShortName string `json:"short_name"` - Country string `json:"country"` - Website string `json:"website"` - Host string `json:"host"` + ShortName string `json:"short_name"` + Country string `json:"country"` + Website firstWebsiteField `json:"website"` + Host string `json:"host"` } `json:"data"` Total int `json:"total"` } @@ -52,7 +80,7 @@ func FetchFIRSTTeams(ctx context.Context, client *fetch.Client) ([]FIRSTTeam, er } for _, team := range resp.Data { - website := strings.TrimSpace(team.Website) + website := strings.TrimSpace(string(team.Website)) if website == "" { website = strings.TrimSpace(team.Host) } diff --git a/internal/collector/discover/http.go b/internal/collector/discover/http.go index d1d72b2..c929462 100644 --- a/internal/collector/discover/http.go +++ b/internal/collector/discover/http.go @@ -5,9 +5,14 @@ package discover import ( "context" + "crypto/sha256" + "encoding/hex" + "os" + "path/filepath" "strings" "time" + "github.com/scalytics/euosint/internal/collector/config" "github.com/scalytics/euosint/internal/collector/fetch" ) @@ -43,3 +48,75 @@ func looksTransient(err error) bool { strings.Contains(msg, " eof") || strings.Contains(msg, ": eof") } + +func fetchWikidataTextWithCache(ctx context.Context, cfg config.Config, client *fetch.Client, url string, accept string) ([]byte, error) { + if body, ok := readWikidataCache(cfg, url); ok { + return body, nil + } + headers := map[string]string{ + "User-Agent": cfg.WikimediaUserAgent, + "Api-User-Agent": cfg.WikimediaUserAgent, + } + var lastErr error + for attempt := 0; attempt < 2; attempt++ { + attemptCtx := ctx + cancel := func() {} + if _, ok := ctx.Deadline(); !ok { + attemptCtx, cancel = context.WithTimeout(ctx, 45*time.Second) + } + body, err := client.TextWithHeaders(attemptCtx, url, true, accept, headers) + cancel() + if err == nil { + writeWikidataCache(cfg, url, body) + return body, nil + } + lastErr = err + if !looksTransient(err) || attempt == 1 { + break + } + } + return nil, lastErr +} + +func readWikidataCache(cfg config.Config, url string) ([]byte, bool) { + path := wikidataCacheFile(cfg, url) + if path == "" { + return nil, false + } + info, err := os.Stat(path) + if err != nil { + return nil, false + } + ttl := time.Duration(cfg.WikidataCacheTTLHours) * time.Hour + if ttl <= 0 { + ttl = 24 * time.Hour + } + if time.Since(info.ModTime()) > ttl { + return nil, false + } + body, err := os.ReadFile(path) + if err != nil || len(body) == 0 { + return nil, false + } + return body, true +} + +func writeWikidataCache(cfg config.Config, url string, body []byte) { + path := wikidataCacheFile(cfg, url) + if path == "" || len(body) == 0 { + return + } + if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { + return + } + _ = os.WriteFile(path, body, 0o644) +} + +func wikidataCacheFile(cfg config.Config, url string) string { + dir := strings.TrimSpace(cfg.WikidataCachePath) + if dir == "" { + return "" + } + sum := sha256.Sum256([]byte(url)) + return filepath.Join(dir, hex.EncodeToString(sum[:])+".json") +} diff --git a/internal/collector/discover/humanitarian.go b/internal/collector/discover/humanitarian.go index d995fd3..32896df 100644 --- a/internal/collector/discover/humanitarian.go +++ b/internal/collector/discover/humanitarian.go @@ -8,8 +8,10 @@ import ( "encoding/json" "fmt" "net/url" + "sort" "strings" + "github.com/scalytics/euosint/internal/collector/config" "github.com/scalytics/euosint/internal/collector/fetch" ) @@ -21,75 +23,99 @@ type HumanitarianOrg struct { Website string } -// The SPARQL query finds humanitarian, disaster-relief, and emergency management -// agencies with official websites. Covers: -// - Emergency management agency (Q895526) -// - Humanitarian aid organization (Q15220109) -// - Disaster management (Q1460420) -// - Civil protection (Q1066476) -const humanitarianQuery = ` +var humanitarianTypeIDs = []string{ + "Q895526", + "Q15220109", + "Q1460420", + "Q1066476", +} + +func buildHumanitarianQuery(typeIDs []string) string { + values := make([]string, 0, len(typeIDs)) + for _, typeID := range typeIDs { + typeID = strings.TrimSpace(typeID) + if typeID == "" { + continue + } + values = append(values, "wd:"+typeID) + } + return fmt.Sprintf(` SELECT ?org ?orgLabel ?website ?countryLabel ?countryCode WHERE { - VALUES ?type { - wd:Q895526 - wd:Q15220109 - wd:Q1460420 - wd:Q1066476 - } + VALUES ?type { %s } ?org wdt:P31/wdt:P279* ?type ; wdt:P856 ?website ; wdt:P17 ?country . ?country wdt:P297 ?countryCode . SERVICE wikibase:label { bd:serviceParam wikibase:language "en" . } } -` +`, strings.Join(values, " ")) +} // FetchHumanitarianOrgs queries Wikidata for humanitarian, emergency management, // and civil protection agencies worldwide. -func FetchHumanitarianOrgs(ctx context.Context, client *fetch.Client) ([]HumanitarianOrg, error) { - query := strings.TrimSpace(humanitarianQuery) - reqURL := wikidataSPARQL + "?format=json&query=" + url.QueryEscape(query) - body, err := fetchTextWithRetry(ctx, client, reqURL, "application/sparql-results+json, application/json;q=0.9") - if err != nil { - return nil, fmt.Errorf("wikidata SPARQL humanitarian: %w", err) - } - - var resp struct { - Results struct { - Bindings []struct { - OrgLabel struct{ Value string } `json:"orgLabel"` - Website struct{ Value string } `json:"website"` - CountryLabel struct{ Value string } `json:"countryLabel"` - CountryCode struct{ Value string } `json:"countryCode"` - } `json:"bindings"` - } `json:"results"` - } - if err := json.Unmarshal(body, &resp); err != nil { - return nil, fmt.Errorf("wikidata SPARQL humanitarian parse: %w", err) - } - +func FetchHumanitarianOrgs(ctx context.Context, cfg config.Config, client *fetch.Client) ([]HumanitarianOrg, error) { + var failures []string seen := map[string]struct{}{} var orgs []HumanitarianOrg - for _, b := range resp.Results.Bindings { - website := strings.TrimRight(strings.TrimSpace(b.Website.Value), "/") - if website == "" { - continue - } - u, err := url.Parse(website) + + for _, chunk := range chunkTypeIDs(humanitarianTypeIDs, 2) { + query := strings.TrimSpace(buildHumanitarianQuery(chunk)) + reqURL := wikidataSPARQL + "?format=json&query=" + url.QueryEscape(query) + body, err := fetchWikidataTextWithCache(ctx, cfg, client, reqURL, "application/sparql-results+json, application/json;q=0.9") if err != nil { + failures = append(failures, fmt.Sprintf("%s: %v", strings.Join(chunk, ","), err)) continue } - host := strings.ToLower(u.Hostname()) - if _, ok := seen[host]; ok { + + var resp struct { + Results struct { + Bindings []struct { + OrgLabel struct{ Value string } `json:"orgLabel"` + Website struct{ Value string } `json:"website"` + CountryLabel struct{ Value string } `json:"countryLabel"` + CountryCode struct{ Value string } `json:"countryCode"` + } `json:"bindings"` + } `json:"results"` + } + if err := json.Unmarshal(body, &resp); err != nil { + failures = append(failures, fmt.Sprintf("%s: parse: %v", strings.Join(chunk, ","), err)) continue } - seen[host] = struct{}{} - orgs = append(orgs, HumanitarianOrg{ - Name: b.OrgLabel.Value, - Country: b.CountryLabel.Value, - CountryCode: strings.ToUpper(strings.TrimSpace(b.CountryCode.Value)), - Website: website, - }) + for _, b := range resp.Results.Bindings { + website := strings.TrimRight(strings.TrimSpace(b.Website.Value), "/") + if website == "" { + continue + } + u, err := url.Parse(website) + if err != nil { + continue + } + host := strings.ToLower(u.Hostname()) + if _, ok := seen[host]; ok { + continue + } + seen[host] = struct{}{} + + orgs = append(orgs, HumanitarianOrg{ + Name: b.OrgLabel.Value, + Country: b.CountryLabel.Value, + CountryCode: strings.ToUpper(strings.TrimSpace(b.CountryCode.Value)), + Website: website, + }) + } + } + sort.Slice(orgs, func(i, j int) bool { + if orgs[i].Country != orgs[j].Country { + return orgs[i].Country < orgs[j].Country + } + return orgs[i].Name < orgs[j].Name + }) + if len(orgs) > 0 { + return orgs, nil + } + if len(failures) > 0 { + return nil, fmt.Errorf("wikidata SPARQL humanitarian: %s", strings.Join(failures, " | ")) } - return orgs, nil + return nil, nil } diff --git a/internal/collector/discover/police.go b/internal/collector/discover/police.go index 76bf52d..ab813ae 100644 --- a/internal/collector/discover/police.go +++ b/internal/collector/discover/police.go @@ -11,6 +11,7 @@ import ( "sort" "strings" + "github.com/scalytics/euosint/internal/collector/config" "github.com/scalytics/euosint/internal/collector/fetch" ) @@ -76,7 +77,7 @@ SELECT ?agency ?agencyLabel ?website ?countryLabel ?countryCode WHERE { // FetchPoliceAgencies queries Wikidata for law-enforcement agencies // worldwide that have official websites. This replaces a static curated // directory and scales to every country automatically. -func FetchPoliceAgencies(ctx context.Context, client *fetch.Client) ([]PoliceAgency, error) { +func FetchPoliceAgencies(ctx context.Context, cfg config.Config, client *fetch.Client) ([]PoliceAgency, error) { // Query Wikidata in smaller chunks so one slow response does not zero out // the entire law-enforcement directory. seen := map[string]struct{}{} @@ -86,7 +87,7 @@ func FetchPoliceAgencies(ctx context.Context, client *fetch.Client) ([]PoliceAge for _, chunk := range chunkTypeIDs(policeAgencyTypeIDs, 2) { query := strings.TrimSpace(buildPoliceAgencyQuery(chunk)) reqURL := wikidataSPARQL + "?format=json&query=" + url.QueryEscape(query) - body, err := fetchTextWithRetry(ctx, client, reqURL, "application/sparql-results+json, application/json;q=0.9") + body, err := fetchWikidataTextWithCache(ctx, cfg, client, reqURL, "application/sparql-results+json, application/json;q=0.9") if err != nil { failures = append(failures, fmt.Sprintf("%s: %v", strings.Join(chunk, ","), err)) continue diff --git a/internal/collector/discover/search_llm.go b/internal/collector/discover/search_llm.go index a308d22..f3d7a2c 100644 --- a/internal/collector/discover/search_llm.go +++ b/internal/collector/discover/search_llm.go @@ -91,11 +91,11 @@ func searchCandidateTarget(ctx context.Context, client searchCompleter, cfg conf } prompt := fmt.Sprintf( - "Find up to %d official or authoritative source URLs for %s in %s relevant to %s intelligence collection. Prefer RSS, Atom, JSON APIs, official newsroom feeds, or durable alert/listing pages. Reject local or municipal sources. Return strict JSON only in the form {\"urls\":[{\"url\":\"https://...\",\"reason\":\"short\"}]}.", + "Find up to %d official RSS or ATOM feed URLs for %s in %s covering %s. Reject local or municipal sources. Return strict JSON only in the form {\"urls\":[{\"url\":\"https://...\",\"reason\":\"short\"}]}. If no official feed exists, return {\"urls\":[]}.", maxURLs, - firstNonEmpty(target.AuthorityName, "the target authority"), + firstNonEmpty(target.AuthorityName, "high-authority OSINT sources"), firstNonEmpty(target.Country, "its jurisdiction"), - firstNonEmpty(target.Category, target.AuthorityType, "public safety"), + searchTopicLabel(target.Category, target.AuthorityType), ) if base := strings.TrimSpace(firstNonEmpty(target.BaseURL, target.URL)); base != "" { prompt += " Known official website: " + base + "." @@ -104,7 +104,7 @@ func searchCandidateTarget(ctx context.Context, client searchCompleter, cfg conf content, err := client.Complete(ctx, []vet.Message{ { Role: "system", - Content: "You are a source discovery assistant. Return strict JSON only. Keep output short. Only list official or highly authoritative URLs likely to be usable as feeds, APIs, or durable listing pages for intelligence-relevant collection.", + Content: "You are a source discovery assistant. Return strict JSON only. Keep output short. Only list official or highly authoritative RSS or ATOM feed URLs suitable for intelligence-relevant collection.", }, { Role: "user", @@ -129,6 +129,9 @@ func searchCandidateTarget(ctx context.Context, client searchCompleter, cfg conf if !looksLikeURL(raw) { continue } + if !looksLikeFeedURL(raw) { + continue + } key := normalizeURL(raw) if key == "" { continue @@ -155,6 +158,30 @@ func searchCandidateTarget(ctx context.Context, client searchCompleter, cfg conf return found, nil } +func searchTopicLabel(category string, authorityType string) string { + switch strings.TrimSpace(category) { + case "missing_person": + return "missing persons and missing children" + case "wanted_suspect": + return "wanted persons, fugitives, and public appeals" + case "terror_warning": + return "terrorism warnings and threat notices" + case "organized_crime": + return "organized crime and major criminal investigations" + case "travel_warning": + return "travel warnings and travel advisories" + case "cyber_advisory": + return "cyber advisories and security alerts" + case "public_appeal": + return "public appeals, wanted persons, and missing persons" + default: + if strings.TrimSpace(authorityType) != "" { + return authorityType + " intelligence collection" + } + return "intelligence collection" + } +} + func decodeLLMSearchResponse(content string) (llmSearchResponse, error) { content = strings.TrimSpace(content) if match := searchJSONBlockRe.FindString(content); match != "" { @@ -174,3 +201,11 @@ func looksLikeURL(raw string) bool { } return (parsed.Scheme == "https" || parsed.Scheme == "http") && parsed.Host != "" } + +func looksLikeFeedURL(raw string) bool { + raw = strings.ToLower(strings.TrimSpace(raw)) + return strings.Contains(raw, "rss") || + strings.Contains(raw, "atom") || + strings.HasSuffix(raw, ".xml") || + strings.Contains(raw, "/feed") +} diff --git a/internal/collector/fetch/client.go b/internal/collector/fetch/client.go index 7fb128b..3fca586 100644 --- a/internal/collector/fetch/client.go +++ b/internal/collector/fetch/client.go @@ -49,6 +49,10 @@ func NewWithHTTPClient(cfg config.Config, httpClient *http.Client) *Client { } func (c *Client) Text(ctx context.Context, url string, followRedirects bool, accept string) ([]byte, error) { + return c.TextWithHeaders(ctx, url, followRedirects, accept, nil) +} + +func (c *Client) TextWithHeaders(ctx context.Context, url string, followRedirects bool, accept string, extraHeaders map[string]string) ([]byte, error) { req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { return nil, fmt.Errorf("build request %s: %w", url, err) @@ -67,6 +71,12 @@ func (c *Client) Text(ctx context.Context, url string, followRedirects bool, acc req.Header.Set("Sec-Fetch-Mode", "navigate") req.Header.Set("Sec-Fetch-Site", "none") req.Header.Set("Sec-Fetch-User", "?1") + for key, value := range extraHeaders { + if strings.TrimSpace(key) == "" || strings.TrimSpace(value) == "" { + continue + } + req.Header.Set(key, value) + } client := c.httpClient if !followRedirects { From 4b452d40f1ca60bc49089e952ff5abd3f16d13eb Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 17:13:40 +0100 Subject: [PATCH 06/58] chore(ui): refresh Scalytics OSINT branding --- index.html | 2 +- public/favicon-globe.svg | 21 --------------------- public/favicon-shield.svg | 25 +++++++++++++++++++++++++ src/App.tsx | 2 +- src/components/Header.tsx | 8 ++++---- 5 files changed, 31 insertions(+), 27 deletions(-) delete mode 100644 public/favicon-globe.svg create mode 100644 public/favicon-shield.svg diff --git a/index.html b/index.html index b924e91..c8d44cc 100644 --- a/index.html +++ b/index.html @@ -7,7 +7,7 @@ - + - - - - - - - - - - - - - - - - - - - - diff --git a/public/favicon-shield.svg b/public/favicon-shield.svg new file mode 100644 index 0000000..af0fd9e --- /dev/null +++ b/public/favicon-shield.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + diff --git a/src/App.tsx b/src/App.tsx index c00f60d..199d1b6 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -275,7 +275,7 @@ export default function App() {
- Open Source Intelligence // World monitor + Scalytics OSINT // Open Source Intelligence Console {selectedSourceIds.length > 0 ? `Scoped to ${selectedSourceIds.length} feeds` diff --git a/src/components/Header.tsx b/src/components/Header.tsx index da545c9..a6f3054 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -502,15 +502,15 @@ export function Header({
-
- +
+
- Scalytics Intelligence + Scalytics OSINT
- Open Source Intelligence + Open Source Intelligence Console
From f8f6b70ecfd20cf040574b0d4094712986adbbf3 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 18:01:05 +0100 Subject: [PATCH 07/58] feat(ui): add health_emergency, intelligence_report, emergency_management categories New category types with theme colors and icons for expanded source coverage. --- src/index.css | 3 +++ src/lib/severity.ts | 12 ++++++++++++ src/types/alert.ts | 5 ++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/index.css b/src/index.css index c7a43f8..c1745fa 100644 --- a/src/index.css +++ b/src/index.css @@ -41,6 +41,9 @@ --color-cat-terrorism: #a34c4c; --color-cat-private: #8f6a46; --color-cat-travel: #c27a3a; + --color-cat-health: #4ca38c; + --color-cat-intel: #7a6eab; + --color-cat-emergency: #b85c4a; } * { diff --git a/src/lib/severity.ts b/src/lib/severity.ts index 4a7e71a..43068f1 100644 --- a/src/lib/severity.ts +++ b/src/lib/severity.ts @@ -50,6 +50,9 @@ export const categoryLabels: Record = { public_safety: "Public Safety", private_sector: "Private Sector", travel_warning: "Travel Warning", + health_emergency: "Health Emergency", + intelligence_report: "Intelligence Report", + emergency_management: "Emergency Management", }; export const categoryOrder: AlertCategory[] = [ @@ -67,6 +70,9 @@ export const categoryOrder: AlertCategory[] = [ "public_safety", "terrorism_tip", "travel_warning", + "health_emergency", + "intelligence_report", + "emergency_management", ]; /** @@ -88,6 +94,9 @@ export const categoryBadge: Record = { terrorism_tip: "bg-cat-terrorism/15 text-cat-terrorism border-cat-terrorism/30", private_sector: "bg-cat-private/15 text-cat-private border-cat-private/30", travel_warning: "bg-cat-travel/15 text-cat-travel border-cat-travel/30", + health_emergency: "bg-cat-health/15 text-cat-health border-cat-health/30", + intelligence_report: "bg-cat-intel/15 text-cat-intel border-cat-intel/30", + emergency_management: "bg-cat-emergency/15 text-cat-emergency border-cat-emergency/30", }; export const categoryIcons: Record = { @@ -105,6 +114,9 @@ export const categoryIcons: Record = { public_safety: "Siren", private_sector: "Building", travel_warning: "Plane", + health_emergency: "HeartPulse", + intelligence_report: "Eye", + emergency_management: "Siren", }; export function freshnessLabel(hours: number): string { diff --git a/src/types/alert.ts b/src/types/alert.ts index a0aeb94..d124d0f 100644 --- a/src/types/alert.ts +++ b/src/types/alert.ts @@ -20,7 +20,10 @@ export type AlertCategory = | "fraud_alert" | "public_safety" | "private_sector" - | "travel_warning"; + | "travel_warning" + | "health_emergency" + | "intelligence_report" + | "emergency_management"; export type AuthorityType = | "police" | "national_security" From c755264047c92c5095b923d4477d0946bcbe7077 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 18:01:15 +0100 Subject: [PATCH 08/58] feat(collector): add local crime downranking and Interpol pagination Routine domestic police operations (raids, drug busts, sentencing) are penalised -0.20 unless cross-border signals are present. Interpol fetcher uses polite paginated API (20/page, 2s delay). --- internal/collector/normalize/normalize.go | 30 ++++++++ .../collector/normalize/normalize_test.go | 50 +++++++++++++ internal/collector/run/run.go | 75 +++++++++++++++---- 3 files changed, 140 insertions(+), 15 deletions(-) diff --git a/internal/collector/normalize/normalize.go b/internal/collector/normalize/normalize.go index 0f89607..0661db8 100644 --- a/internal/collector/normalize/normalize.go +++ b/internal/collector/normalize/normalize.go @@ -62,6 +62,29 @@ var ( regexp.MustCompile(`(?i)\b(?:vulnerability|exploit|patch|advisory|defend|defensive)\b`), regexp.MustCompile(`(?i)\b(?:soc|siem|incident response|malware analysis)\b`), } + // localCrimePatterns match routine domestic police operations that lack + // cross-border or international intelligence significance. + localCrimePatterns = []*regexp.Regexp{ + regexp.MustCompile(`(?i)\b(?:operac[aã]o|opera[çc][aã]o|operation)\b.*\b(?:busca|raid|search|apreens[aã]o|seizure)\b`), + regexp.MustCompile(`(?i)\b(?:drug bust|drug seizure|narcotics seized|heroin|cocaine|cannabis|marijuana)\b.*\b(?:kg|kilos?|grams?|pounds?|tonnes?)\b`), + regexp.MustCompile(`(?i)\b(?:burglary|robbery|theft|shoplifting|pickpocket|break-?in|car theft|vehicle theft)\b`), + regexp.MustCompile(`(?i)\b(?:domestic (?:violence|abuse|dispute)|bar fight|pub brawl|assault|gbh|abh)\b`), + regexp.MustCompile(`(?i)\b(?:drunk driv|dui|dwi|speeding|traffic (?:offence|offense|violation)|road rage)\b`), + regexp.MustCompile(`(?i)\b(?:sentenced to|prison sentence|jail (?:term|sentence)|community service|probation order)\b`), + regexp.MustCompile(`(?i)\b(?:mortu[aá]ri[ao]|autopsy|autópsia|post-?mortem|inquest|coroner)\b`), + regexp.MustCompile(`(?i)\b(?:local police|polícia local|commissariat|poste de police|comisaría)\b`), + } + // crossBorderSignals indicate international/strategic significance that + // should prevent local-crime downranking. + crossBorderSignals = []*regexp.Regexp{ + regexp.MustCompile(`(?i)\b(?:interpol|europol|eurojust|frontex|five eyes|nato)\b`), + regexp.MustCompile(`(?i)\b(?:cross-?border|transnational|international|multi-?country|joint (?:operation|investigation))\b`), + regexp.MustCompile(`(?i)\b(?:terror(?:ism|ist)?|extremis[tm]|radicaliz|foreign fighter)\b`), + regexp.MustCompile(`(?i)\b(?:cyber.?attack|state-?sponsored|apt|espionage|intelligence)\b`), + regexp.MustCompile(`(?i)\b(?:trafficking|smuggling|organized crime|money laundering|sanctions evasion)\b`), + regexp.MustCompile(`(?i)\b(?:critical infrastructure|national security|chemical|biological|nuclear|radiological)\b`), + regexp.MustCompile(`(?i)\b(?:mass casualty|mass shooting|bombing|explosion|hostage)\b`), + } assistancePatterns = []*regexp.Regexp{ regexp.MustCompile(`(?i)\b(?:report(?:\s+a)?(?:\s+crime)?|submit (?:a )?tip|tip[-\s]?off)\b`), regexp.MustCompile(`(?i)\b(?:contact (?:police|authorities|law enforcement)|hotline|helpline)\b`), @@ -519,6 +542,13 @@ func score(cfg config.Config, alert model.Alert, feed FeedContext) *model.Triage if hasCertification && !hasIncident && !hasTechnical { add(-0.22, "certification/training/standards content") } + // Downrank routine local crime stories from police feeds unless + // they carry cross-border or strategic intelligence significance. + hasLocalCrime := hasAny(text, localCrimePatterns) + hasCrossBorder := hasAny(text, crossBorderSignals) + if hasLocalCrime && !hasCrossBorder && !hasTechnical { + add(-0.20, "routine local crime without cross-border significance") + } if !hasTechnical && !hasIncident && (hasNarrative || hasGeneral) { add(-0.08, "weak incident evidence relative to narrative cues") } diff --git a/internal/collector/normalize/normalize_test.go b/internal/collector/normalize/normalize_test.go index 9c36053..2e27b70 100644 --- a/internal/collector/normalize/normalize_test.go +++ b/internal/collector/normalize/normalize_test.go @@ -9,6 +9,7 @@ import ( "github.com/scalytics/euosint/internal/collector/config" "github.com/scalytics/euosint/internal/collector/model" + "github.com/scalytics/euosint/internal/collector/parse" ) func TestDeduplicatePrefersHigherScore(t *testing.T) { @@ -72,3 +73,52 @@ func TestInterpolAlertUsesNoticeCountryAndStableID(t *testing.T) { t.Fatalf("expected source authority to remain INTERPOL, got %#v", alert.Source) } } + +func TestLocalCrimeDownranked(t *testing.T) { + cfg := config.Default() + ctx := Context{Config: cfg, Now: time.Date(2026, 3, 16, 0, 0, 0, 0, time.UTC)} + meta := model.RegistrySource{ + Type: "rss", + Category: "public_appeal", + Source: model.SourceMetadata{ + SourceID: "pj-pt", + AuthorityName: "Polícia Judiciária", + Country: "Portugal", + CountryCode: "PT", + Region: "Europe", + AuthorityType: "police", + }, + } + + // Local crime: police raid on a mortuary — no cross-border significance. + localItem := parse.FeedItem{ + Title: "Operação Rigor Mortis – PJ realiza buscas em casa mortuária e em domicílios", + Link: "https://www.policiajudiciaria.pt/operacao-rigor-mortis/", + Published: "2026-03-15T10:00:00Z", + Summary: "A Polícia Judiciária realizou buscas em casa mortuária. Autopsy fraud investigation.", + } + localAlert := RSSItem(ctx, meta, localItem) + if localAlert == nil { + t.Fatal("expected local crime alert to be normalized") + } + if localAlert.Triage.RelevanceScore >= cfg.IncidentRelevanceThreshold { + t.Fatalf("expected local crime to be below threshold, got %.3f (threshold %.3f)", + localAlert.Triage.RelevanceScore, cfg.IncidentRelevanceThreshold) + } + + // Cross-border crime: Europol joint operation — should stay above threshold. + crossBorderItem := parse.FeedItem{ + Title: "Operação conjunta PJ-Europol — rede transnacional de tráfico desmantelada", + Link: "https://www.policiajudiciaria.pt/operacao-europol/", + Published: "2026-03-15T10:00:00Z", + Summary: "Joint operation with Europol dismantled cross-border trafficking network. Drug seizure of 500 kg cocaine.", + } + crossBorderAlert := RSSItem(ctx, meta, crossBorderItem) + if crossBorderAlert == nil { + t.Fatal("expected cross-border alert to be normalized") + } + if crossBorderAlert.Triage.RelevanceScore < localAlert.Triage.RelevanceScore { + t.Fatalf("expected cross-border alert (%.3f) to score higher than local crime (%.3f)", + crossBorderAlert.Triage.RelevanceScore, localAlert.Triage.RelevanceScore) + } +} diff --git a/internal/collector/run/run.go b/internal/collector/run/run.go index 1e45d6c..e9bef2d 100644 --- a/internal/collector/run/run.go +++ b/internal/collector/run/run.go @@ -103,6 +103,23 @@ func (r Runner) runOnce(ctx context.Context, cfg config.Config) error { startedAt := time.Now().UTC() fetcher := fetch.FetcherFor(source.FetchMode, client, browser) batch, err := r.fetchSource(ctx, fetcher, browser, nctx, source, categoryDictionary) + + // Retry once for transient errors (timeout, EOF) after a short backoff. + if err != nil { + errClass, _, _ := classifySourceError(err) + if (errClass == "timeout" || errClass == "eof" || errClass == "transient") && ctx.Err() == nil { + fmt.Fprintf(r.stderr, "RETRY %s (transient %s): %v\n", source.Source.AuthorityName, errClass, err) + retryDelay := 3 * time.Second + select { + case <-time.After(retryDelay): + case <-ctx.Done(): + } + if ctx.Err() == nil { + batch, err = r.fetchSource(ctx, fetcher, browser, nctx, source, categoryDictionary) + } + } + } + entry := model.SourceHealthEntry{ SourceID: source.Source.SourceID, AuthorityName: source.Source.AuthorityName, @@ -291,23 +308,55 @@ func (r Runner) fetchKEV(ctx context.Context, fetcher fetch.Fetcher, nctx normal } func (r Runner) fetchInterpol(ctx context.Context, fetcher fetch.Fetcher, browser *fetch.BrowserClient, nctx normalize.Context, source model.RegistrySource) ([]model.Alert, error) { - var ( - body []byte - err error - ) - if browser != nil { - body, err = fetchInterpolViaBrowser(ctx, browser, source) + limit := perSourceLimit(nctx.Config, source) + pageSize := 20 + var allNotices []model.Alert + + for page := 1; len(allNotices) < limit; page++ { + pageURL := buildInterpolPageURL(source.FeedURL, page, pageSize) + body, err := fetcher.Text(ctx, pageURL, source.FollowRedirects, "application/json") + if err != nil { + // If first page fails, try browser fallback for the whole batch. + if page == 1 && browser != nil { + fmt.Fprintf(r.stderr, "WARN %s: stealth fetch failed, trying browser fallback: %v\n", source.Source.AuthorityName, err) + bBody, bErr := fetchInterpolViaBrowser(ctx, browser, source) + if bErr == nil && len(bBody) > 0 { + return parseInterpolNotices(nctx, source, bBody) + } + } + break + } + batch, err := parseInterpolNotices(nctx, source, body) if err != nil { - fmt.Fprintf(r.stderr, "WARN %s: browser notice capture failed, falling back to direct fetch: %v\n", source.Source.AuthorityName, err) + break + } + allNotices = append(allNotices, batch...) + if len(batch) < pageSize { + break // last page + } + // Polite delay between page requests. + select { + case <-time.After(2 * time.Second): + case <-ctx.Done(): + return allNotices, nil } } - if len(body) == 0 { - body, err = fetcher.Text(ctx, source.FeedURL, source.FollowRedirects, "application/json") + if len(allNotices) > limit { + allNotices = allNotices[:limit] } + return allNotices, nil +} + +func buildInterpolPageURL(baseURL string, page int, pageSize int) string { + u, err := url.Parse(baseURL) if err != nil { - return nil, err + return baseURL } - return parseInterpolNotices(nctx, source, body) + q := u.Query() + q.Set("page", fmt.Sprintf("%d", page)) + q.Set("resultPerPage", fmt.Sprintf("%d", pageSize)) + u.RawQuery = q.Encode() + return u.String() } func parseInterpolNotices(nctx normalize.Context, source model.RegistrySource, body []byte) ([]model.Alert, error) { @@ -332,12 +381,8 @@ func parseInterpolNotices(nctx normalize.Context, source model.RegistrySource, b if err := json.Unmarshal(body, &doc); err != nil { return nil, err } - limit := perSourceLimit(nctx.Config, source) out := []model.Alert{} for _, notice := range doc.Embedded.Notices { - if len(out) == limit { - break - } titlePrefix := "INTERPOL Red Notice" if source.Type == "interpol-yellow-json" { titlePrefix = "INTERPOL Yellow Notice" From d04739d4e91b558ce00b09db2c6092c2365b8d97 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 18:01:23 +0100 Subject: [PATCH 09/58] feat(config): bump default max-per-source to 40 Prevents flat top-authorities ranking where every source caps at 20. Cyber advisory sources are individually capped at 15 in the registry. --- internal/collector/config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/collector/config/config.go b/internal/collector/config/config.go index b8c11d3..8d0fcd0 100644 --- a/internal/collector/config/config.go +++ b/internal/collector/config/config.go @@ -17,7 +17,7 @@ const ( defaultRegistryPath = "registry/sources.db" defaultTimeoutMS = 15000 defaultIntervalMS = 900000 - defaultMaxPerSource = 20 + defaultMaxPerSource = 40 defaultMaxAgeDays = 180 defaultRemovedDays = 14 defaultMaxBodyBytes = 2 * 1024 * 1024 From bfdcf60b4eb57c200ff17de83dbb5fcc87b54462 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 18:01:45 +0100 Subject: [PATCH 10/58] feat(registry): expand to 257 sources across 92 countries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Interpol Red/Yellow Notices (paginated API) - Humanitarian: ICRC, UNHCR, WHO, ReliefWeb, WFP, MSF - Conflict: ICG, SIPRI, NATO, UN SC, OSCE, African Union - Intelligence: CIA, MI5, GCHQ, BfV, BND, DGSI, AIVD, SÄPO, ASIO, CSIS - Health: ECDC, CDC, ProMED, WHO emergencies - Emergency: GDACS, FEMA, EU ERCC, USGS - Ukraine: CERT-UA, NSDC, SBU, National Police - Nordics: full coverage NO/DK/FI/IS/SE (police, intel, CERT, travel) - Eastern Europe: PL/CZ/HU/RO/SK/BG/RS/GE/MD police and intel - Middle East: Israel, UAE, Saudi, Jordan, Qatar CERTs - Africa: AU, Egypt, Morocco, Rwanda, Ethiopia, Senegal, Algeria - Asia: Taiwan, China, Vietnam, Pakistan, Bangladesh, Sri Lanka, Mongolia - Sanctions: OFAC, EU, UN, FATF, OpenSanctions - Financial fraud: FCA, BaFin, ESMA, SEC, FinCEN, FINMA + 6 EU regulators - Organized crime: OCCRP, UNODC, ENFAST, OLAF, EPPO, DIA, SFO, DEA, ATF - Europol updated to CMS API RSS, duplicate entry removed - Cyber advisory sources capped at max_items=15 --- registry/source_registry.json | 2767 ++++++++++++++++++++++++++++++++- 1 file changed, 2729 insertions(+), 38 deletions(-) diff --git a/registry/source_registry.json b/registry/source_registry.json index fb7066c..2167396 100644 --- a/registry/source_registry.json +++ b/registry/source_registry.json @@ -19,7 +19,8 @@ "label": "Report to CISA", "url": "https://www.cisa.gov/report", "notes": "Use 911 for emergencies." - } + }, + "max_items": 15 }, { "type": "rss", @@ -79,7 +80,7 @@ "authority_type": "police", "base_url": "https://www.europol.europa.eu" }, - "feed_url": "https://www.europol.europa.eu/rss.xml", + "feed_url": "https://www.europol.europa.eu/cms/api/rss/news", "category": "public_appeal", "region_tag": "EU", "lat": 52.09, @@ -108,7 +109,8 @@ "reporting": { "label": "Report to NCSC", "url": "https://www.ncsc.gov.uk/section/about-this-website/report-scam-website" - } + }, + "max_items": 15 }, { "type": "rss", @@ -129,7 +131,8 @@ "reporting": { "label": "Report to NCSC", "url": "https://www.ncsc.gov.uk/section/about-this-website/report-scam-website" - } + }, + "max_items": 15 }, { "type": "rss", @@ -220,7 +223,8 @@ "phone": "1-866-787-4722", "email": "soc@cisecurity.org", "notes": "24/7 Security Operations Center for state, local, tribal, and territorial governments." - } + }, + "max_items": 15 }, { "type": "rss", @@ -264,7 +268,8 @@ "label": "Report to CERT-FR", "url": "https://www.cert.ssi.gouv.fr/contact/", "email": "cert-fr@ssi.gouv.fr" - } + }, + "max_items": 15 }, { "type": "rss", @@ -286,7 +291,8 @@ "label": "Report to NCSC-NL", "url": "https://www.ncsc.nl/contact/kwetsbaarheid-melden", "email": "cert@ncsc.nl" - } + }, + "max_items": 15 }, { "type": "rss", @@ -308,7 +314,8 @@ "label": "Report to JPCERT/CC", "url": "https://www.jpcert.or.jp/english/ir/form.html", "email": "info@jpcert.or.jp" - } + }, + "max_items": 15 }, { "type": "rss", @@ -355,7 +362,8 @@ "phone": "1-888-282-0870", "email": "central@cisa.dhs.gov", "notes": "Use 911 for emergencies." - } + }, + "max_items": 15 }, { "type": "html-list", @@ -634,7 +642,8 @@ "label": "Report to ACSC", "url": "https://www.cyber.gov.au/report-and-recover/report", "phone": "1300 292 371" - } + }, + "max_items": 15 }, { "type": "rss", @@ -789,7 +798,8 @@ "url": "https://www.cert-in.org.in/", "email": "incident@cert-in.org.in", "phone": "+91-11-24368572" - } + }, + "max_items": 15 }, { "type": "rss", @@ -818,7 +828,8 @@ "url": "https://www.csa.gov.sg/singcert/reporting", "email": "singcert@csa.gov.sg", "phone": "+65 6323 5052" - } + }, + "max_items": 15 }, { "type": "rss", @@ -870,7 +881,8 @@ "url": "https://www.hkcert.org/report-incident", "email": "hkcert@hkcert.org", "phone": "+852 8105 6060" - } + }, + "max_items": 15 }, { "type": "rss", @@ -1131,7 +1143,8 @@ "label": "Report Cybercrime to PDI", "url": "https://www.pdichile.cl/", "phone": "134 (PDI Emergency)" - } + }, + "max_items": 15 }, { "type": "rss", @@ -1435,7 +1448,8 @@ "label": "Report to ThaiCERT", "url": "https://www.thaicert.or.th/", "email": "op@thaicert.or.th" - } + }, + "max_items": 15 }, { "type": "rss", @@ -1462,7 +1476,8 @@ "label": "Report to MyCERT", "url": "https://www.mycert.org.my/portal/report-incident", "email": "mycert@cybersecurity.my" - } + }, + "max_items": 15 }, { "type": "rss", @@ -1489,7 +1504,8 @@ "label": "Report to BSSN", "url": "https://bssn.go.id/", "notes": "Use official BSSN contact channels for incident reporting." - } + }, + "max_items": 15 }, { "type": "rss", @@ -1560,7 +1576,8 @@ "label": "Report a Cyber Incident", "url": "https://www.cyber.gc.ca/en/incident-management", "phone": "1-833-CYBER-88" - } + }, + "max_items": 15 }, { "type": "rss", @@ -1582,7 +1599,8 @@ "reporting": { "label": "Report Cyber Incident to USOM", "url": "https://www.usom.gov.tr/bildirim" - } + }, + "max_items": 15 }, { "type": "html-list", @@ -2160,7 +2178,8 @@ "reporting": { "label": "Report to BSI", "url": "https://www.bsi.bund.de/DE/IT-Sicherheitsvorfall/it-sicherheitsvorfall_node.html" - } + }, + "max_items": 15 }, { "type": "rss", @@ -2181,7 +2200,8 @@ "reporting": { "label": "Report to BSI", "url": "https://www.bsi.bund.de/DE/IT-Sicherheitsvorfall/it-sicherheitsvorfall_node.html" - } + }, + "max_items": 15 }, { "type": "rss", @@ -2202,7 +2222,8 @@ "reporting": { "label": "Report to BSI", "url": "https://www.bsi.bund.de/DE/IT-Sicherheitsvorfall/it-sicherheitsvorfall_node.html" - } + }, + "max_items": 15 }, { "type": "rss", @@ -2223,7 +2244,8 @@ "reporting": { "label": "Report to BSI", "url": "https://www.bsi.bund.de/DE/IT-Sicherheitsvorfall/it-sicherheitsvorfall_node.html" - } + }, + "max_items": 15 }, { "type": "rss", @@ -2244,7 +2266,8 @@ "reporting": { "label": "Report to BSI", "url": "https://www.bsi.bund.de/DE/IT-Sicherheitsvorfall/it-sicherheitsvorfall_node.html" - } + }, + "max_items": 15 }, { "type": "rss", @@ -2265,7 +2288,8 @@ "reporting": { "label": "Report to SANS ISC", "url": "https://isc.sans.edu/contact.html" - } + }, + "max_items": 15 }, { "type": "rss", @@ -2286,7 +2310,8 @@ "reporting": { "label": "Report to CERT.at", "url": "https://cert.at/de/melden" - } + }, + "max_items": 15 }, { "type": "rss", @@ -2307,7 +2332,8 @@ "reporting": { "label": "Report to CCN-CERT", "url": "https://www.ccn-cert.cni.es/es/comunicacion-eventos/contacto.html" - } + }, + "max_items": 15 }, { "type": "rss", @@ -2328,7 +2354,8 @@ "reporting": { "label": "Report to CERT-SE", "url": "https://www.cert.se/om-cert-se/rapportera-en-incident/" - } + }, + "max_items": 15 }, { "type": "rss", @@ -2349,7 +2376,8 @@ "reporting": { "label": "Report to CERT.PL", "url": "https://incydent.cert.pl/" - } + }, + "max_items": 15 }, { "type": "rss", @@ -2370,7 +2398,8 @@ "reporting": { "label": "Report to CERT.LV", "url": "https://www.cert.lv/en/report" - } + }, + "max_items": 15 }, { "type": "rss", @@ -2391,7 +2420,8 @@ "reporting": { "label": "Report to CERT.hr", "url": "https://www.cert.hr/prijava-incidenta/" - } + }, + "max_items": 15 }, { "type": "rss", @@ -2412,7 +2442,8 @@ "reporting": { "label": "Report to SI-CERT", "url": "https://www.cert.si/en/report/" - } + }, + "max_items": 15 }, { "type": "rss", @@ -2433,7 +2464,8 @@ "reporting": { "label": "Report to DNSC", "url": "https://dnsc.ro/sesizare" - } + }, + "max_items": 15 }, { "type": "html-list", @@ -2454,7 +2486,8 @@ "reporting": { "label": "Report to NCSC", "url": "https://www.ncsc.admin.ch/ncsc/en/home/infos-fuer/infos-it-spezialisten/themen/schwachstelle-melden.html" - } + }, + "max_items": 15 }, { "type": "rss", @@ -2597,7 +2630,8 @@ "reporting": { "label": "Report to CERT-EE", "url": "https://www.ria.ee/en/cyber-security/cert-ee/reporting-incident" - } + }, + "max_items": 15 }, { "type": "html-list", @@ -2618,7 +2652,8 @@ "reporting": { "label": "Report to NKSC", "url": "https://www.nksc.lt/en/report.html" - } + }, + "max_items": 15 }, { "type": "html-list", @@ -2639,7 +2674,8 @@ "reporting": { "label": "Report to NCSA Greece", "url": "https://www.nis.gr/el/contact/" - } + }, + "max_items": 15 }, { "type": "html-list", @@ -2660,7 +2696,8 @@ "reporting": { "label": "Report to GovCERT.bg", "url": "https://www.govcert.bg/" - } + }, + "max_items": 15 }, { "type": "travelwarning-json", @@ -2735,5 +2772,2659 @@ "url": "https://travel.state.gov/content/travel/en/traveladvisories/traveladvisories.html", "notes": "Travel advisories for US citizens abroad." } + }, + { + "type": "interpol-red-json", + "source": { + "source_id": "interpol-red", + "authority_name": "INTERPOL Red Notices", + "country": "France", + "country_code": "FR", + "region": "International", + "authority_type": "police", + "base_url": "https://ws-public.interpol.int" + }, + "feed_url": "https://ws-public.interpol.int/notices/v1/red?resultPerPage=20&page=1", + "category": "wanted_suspect", + "region_tag": "INT", + "lat": 48.86, + "lng": 2.35, + "max_items": 200 + }, + { + "type": "interpol-yellow-json", + "source": { + "source_id": "interpol-yellow", + "authority_name": "INTERPOL Yellow Notices", + "country": "France", + "country_code": "FR", + "region": "International", + "authority_type": "police", + "base_url": "https://ws-public.interpol.int" + }, + "feed_url": "https://ws-public.interpol.int/notices/v1/yellow?resultPerPage=20&page=1", + "category": "missing_person", + "region_tag": "INT", + "lat": 48.86, + "lng": 2.35, + "max_items": 200 + }, + { + "type": "rss", + "source": { + "source_id": "icrc-news", + "authority_name": "ICRC News", + "country": "Switzerland", + "country_code": "CH", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://www.icrc.org" + }, + "feed_url": "https://www.icrc.org/en/rss", + "category": "humanitarian_security", + "region_tag": "INT", + "lat": 46.22, + "lng": 6.14 + }, + { + "type": "rss", + "source": { + "source_id": "unhcr-news", + "authority_name": "UNHCR News", + "country": "Switzerland", + "country_code": "CH", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://www.unhcr.org" + }, + "feed_url": "https://www.unhcr.org/rss/news.xml", + "category": "humanitarian_security", + "region_tag": "INT", + "lat": 46.22, + "lng": 6.14 + }, + { + "type": "rss", + "source": { + "source_id": "who-disease-outbreak", + "authority_name": "WHO Disease Outbreak News", + "country": "Switzerland", + "country_code": "CH", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://www.who.int" + }, + "feed_url": "https://www.who.int/feeds/entity/don/en/rss.xml", + "category": "health_emergency", + "region_tag": "INT", + "lat": 46.22, + "lng": 6.14 + }, + { + "type": "rss", + "source": { + "source_id": "who-emergencies", + "authority_name": "WHO Health Emergencies", + "country": "Switzerland", + "country_code": "CH", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://www.who.int" + }, + "feed_url": "https://www.who.int/feeds/entity/hac/en/rss.xml", + "category": "health_emergency", + "region_tag": "INT", + "lat": 46.22, + "lng": 6.14 + }, + { + "type": "rss", + "source": { + "source_id": "reliefweb-updates", + "authority_name": "ReliefWeb Updates", + "country": "Global", + "country_code": "INT", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://reliefweb.int" + }, + "feed_url": "https://reliefweb.int/updates/rss.xml", + "category": "humanitarian_security", + "region_tag": "INT", + "lat": 40.75, + "lng": -73.97 + }, + { + "type": "rss", + "source": { + "source_id": "wfp-news", + "authority_name": "World Food Programme News", + "country": "Italy", + "country_code": "IT", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://www.wfp.org" + }, + "feed_url": "https://www.wfp.org/rss.xml", + "category": "humanitarian_security", + "region_tag": "INT", + "lat": 41.88, + "lng": 12.56 + }, + { + "type": "rss", + "source": { + "source_id": "msf-news", + "authority_name": "Médecins Sans Frontières", + "country": "Switzerland", + "country_code": "CH", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://www.msf.org" + }, + "feed_url": "https://www.msf.org/rss/all", + "category": "humanitarian_security", + "region_tag": "INT", + "lat": 46.22, + "lng": 6.14 + }, + { + "type": "rss", + "source": { + "source_id": "icg-crisiswatch", + "authority_name": "International Crisis Group", + "country": "Belgium", + "country_code": "BE", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://www.crisisgroup.org" + }, + "feed_url": "https://www.crisisgroup.org/rss.xml", + "category": "conflict_monitoring", + "region_tag": "INT", + "lat": 50.85, + "lng": 4.35 + }, + { + "type": "rss", + "source": { + "source_id": "sipri-news", + "authority_name": "SIPRI News", + "country": "Sweden", + "country_code": "SE", + "region": "Europe", + "authority_type": "public_safety_program", + "base_url": "https://www.sipri.org" + }, + "feed_url": "https://www.sipri.org/rss.xml", + "category": "conflict_monitoring", + "region_tag": "INT", + "lat": 59.35, + "lng": 17.95 + }, + { + "type": "rss", + "source": { + "source_id": "gdacs-alerts", + "authority_name": "GDACS Natural Disaster Alerts", + "country": "Global", + "country_code": "INT", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://www.gdacs.org" + }, + "feed_url": "https://www.gdacs.org/xml/rss.xml", + "category": "emergency_management", + "region_tag": "INT", + "lat": 45.77, + "lng": 4.83 + }, + { + "type": "rss", + "source": { + "source_id": "cia-newsroom", + "authority_name": "CIA Newsroom", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "intelligence", + "base_url": "https://www.cia.gov" + }, + "feed_url": "https://www.cia.gov/rss/press-releases.xml", + "category": "intelligence_report", + "region_tag": "US", + "lat": 38.95, + "lng": -77.15, + "fetch_mode": "browser" + }, + { + "type": "rss", + "source": { + "source_id": "nsa-advisories", + "authority_name": "NSA Cybersecurity Advisories", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "intelligence", + "base_url": "https://www.nsa.gov" + }, + "feed_url": "https://www.nsa.gov/Press-Room/Press-Releases-Statements/RSS-Feed/", + "category": "cyber_advisory", + "region_tag": "US", + "lat": 39.11, + "lng": -76.77, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "mi5-news", + "authority_name": "MI5 News", + "country": "United Kingdom", + "country_code": "GB", + "region": "Europe", + "authority_type": "intelligence", + "base_url": "https://www.mi5.gov.uk" + }, + "feed_url": "https://www.mi5.gov.uk/UKSecurityNews.xml", + "category": "intelligence_report", + "region_tag": "GB", + "lat": 51.5, + "lng": -0.13 + }, + { + "type": "rss", + "source": { + "source_id": "gchq-news", + "authority_name": "GCHQ News", + "country": "United Kingdom", + "country_code": "GB", + "region": "Europe", + "authority_type": "intelligence", + "base_url": "https://www.gchq.gov.uk" + }, + "feed_url": "https://www.gchq.gov.uk/feeds/news.xml", + "category": "intelligence_report", + "region_tag": "GB", + "lat": 51.9, + "lng": -2.12 + }, + { + "type": "rss", + "source": { + "source_id": "bfv-news", + "authority_name": "BfV (Bundesamt für Verfassungsschutz)", + "country": "Germany", + "country_code": "DE", + "region": "Europe", + "authority_type": "intelligence", + "base_url": "https://www.verfassungsschutz.de" + }, + "feed_url": "https://www.verfassungsschutz.de/SiteGlobals/Functions/RSSFeed/DE/RSSNewsfeed/RSSNewsfeed.xml", + "category": "intelligence_report", + "region_tag": "DE", + "lat": 50.73, + "lng": 7.1 + }, + { + "type": "rss", + "source": { + "source_id": "bnd-news", + "authority_name": "BND (Bundesnachrichtendienst)", + "country": "Germany", + "country_code": "DE", + "region": "Europe", + "authority_type": "intelligence", + "base_url": "https://www.bnd.bund.de" + }, + "feed_url": "https://www.bnd.bund.de/SiteGlobals/Functions/RSSFeed/DE/RSSNewsfeed/RSSNewsfeed.xml", + "category": "intelligence_report", + "region_tag": "DE", + "lat": 52.52, + "lng": 13.38 + }, + { + "type": "rss", + "source": { + "source_id": "dgsi-news", + "authority_name": "DGSI (French Internal Intelligence)", + "country": "France", + "country_code": "FR", + "region": "Europe", + "authority_type": "intelligence", + "base_url": "https://www.dgsi.interieur.gouv.fr" + }, + "feed_url": "https://www.dgsi.interieur.gouv.fr/rss.xml", + "category": "intelligence_report", + "region_tag": "FR", + "lat": 48.86, + "lng": 2.33 + }, + { + "type": "rss", + "source": { + "source_id": "aivd-news", + "authority_name": "AIVD (Dutch Intelligence)", + "country": "Netherlands", + "country_code": "NL", + "region": "Europe", + "authority_type": "intelligence", + "base_url": "https://www.aivd.nl" + }, + "feed_url": "https://www.aivd.nl/rss/nieuws", + "category": "intelligence_report", + "region_tag": "NL", + "lat": 52.08, + "lng": 4.31 + }, + { + "type": "rss", + "source": { + "source_id": "sapo-news", + "authority_name": "SÄPO (Swedish Security Service)", + "country": "Sweden", + "country_code": "SE", + "region": "Europe", + "authority_type": "intelligence", + "base_url": "https://www.sakerhetspolisen.se" + }, + "feed_url": "https://www.sakerhetspolisen.se/rss/nyheter.xml", + "category": "intelligence_report", + "region_tag": "SE", + "lat": 59.33, + "lng": 18.07 + }, + { + "type": "rss", + "source": { + "source_id": "asio-news", + "authority_name": "ASIO (Australian Security Intelligence)", + "country": "Australia", + "country_code": "AU", + "region": "Asia-Pacific", + "authority_type": "intelligence", + "base_url": "https://www.asio.gov.au" + }, + "feed_url": "https://www.asio.gov.au/rss.xml", + "category": "intelligence_report", + "region_tag": "AU", + "lat": -35.28, + "lng": 149.13 + }, + { + "type": "rss", + "source": { + "source_id": "csis-canada", + "authority_name": "CSIS (Canadian Intelligence)", + "country": "Canada", + "country_code": "CA", + "region": "North America", + "authority_type": "intelligence", + "base_url": "https://www.canada.ca/en/security-intelligence-service" + }, + "feed_url": "https://www.canada.ca/en/security-intelligence-service.atom.xml", + "category": "intelligence_report", + "region_tag": "CA", + "lat": 45.42, + "lng": -75.69 + }, + { + "type": "rss", + "source": { + "source_id": "ecdc-news", + "authority_name": "ECDC Disease Threats", + "country": "Sweden", + "country_code": "SE", + "region": "Europe", + "authority_type": "public_safety_program", + "base_url": "https://www.ecdc.europa.eu" + }, + "feed_url": "https://www.ecdc.europa.eu/en/taxonomy/term/1/feed", + "category": "health_emergency", + "region_tag": "EU", + "lat": 59.35, + "lng": 17.94 + }, + { + "type": "rss", + "source": { + "source_id": "cdc-emergency", + "authority_name": "CDC Emergency Preparedness", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "public_safety_program", + "base_url": "https://www.cdc.gov" + }, + "feed_url": "https://tools.cdc.gov/api/v2/resources/media/403420.rss", + "category": "health_emergency", + "region_tag": "US", + "lat": 33.8, + "lng": -84.32 + }, + { + "type": "rss", + "source": { + "source_id": "promed-alerts", + "authority_name": "ProMED Alerts", + "country": "United States", + "country_code": "US", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://promedmail.org" + }, + "feed_url": "https://promedmail.org/feed/", + "category": "health_emergency", + "region_tag": "INT", + "lat": 42.36, + "lng": -71.06 + }, + { + "type": "rss", + "source": { + "source_id": "fema-alerts", + "authority_name": "FEMA Disaster Declarations", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "public_safety_program", + "base_url": "https://www.fema.gov" + }, + "feed_url": "https://www.fema.gov/feeds/disasters", + "category": "emergency_management", + "region_tag": "US", + "lat": 38.88, + "lng": -77.02 + }, + { + "type": "rss", + "source": { + "source_id": "eu-ercc", + "authority_name": "EU Emergency Response (ERCC)", + "country": "Belgium", + "country_code": "BE", + "region": "Europe", + "authority_type": "public_safety_program", + "base_url": "https://ercc.dgecho.eu" + }, + "feed_url": "https://erccportal.jrc.ec.europa.eu/ECHO-Flash/RSS-Feeds/RSS-Latest-Emergencies", + "category": "emergency_management", + "region_tag": "EU", + "lat": 50.85, + "lng": 4.38 + }, + { + "type": "rss", + "source": { + "source_id": "usgs-earthquake", + "authority_name": "USGS Earthquake Alerts", + "country": "United States", + "country_code": "US", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://earthquake.usgs.gov" + }, + "feed_url": "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/significant_week.atom", + "category": "emergency_management", + "region_tag": "INT", + "lat": 37.77, + "lng": -122.42 + }, + { + "type": "rss", + "source": { + "source_id": "ca-travel-advisories", + "authority_name": "Canada Travel Advisories", + "country": "Canada", + "country_code": "CA", + "region": "North America", + "authority_type": "national_security", + "base_url": "https://travel.gc.ca" + }, + "feed_url": "https://travel.gc.ca/travelling/advisories.atom", + "category": "travel_warning", + "region_tag": "CA", + "lat": 45.42, + "lng": -75.69 + }, + { + "type": "rss", + "source": { + "source_id": "au-smartraveller", + "authority_name": "Australia Smartraveller", + "country": "Australia", + "country_code": "AU", + "region": "Asia-Pacific", + "authority_type": "national_security", + "base_url": "https://www.smartraveller.gov.au" + }, + "feed_url": "https://www.smartraveller.gov.au/rss/countries", + "category": "travel_warning", + "region_tag": "AU", + "lat": -35.28, + "lng": 149.13 + }, + { + "type": "rss", + "source": { + "source_id": "nz-safetravel", + "authority_name": "NZ SafeTravel Advisories", + "country": "New Zealand", + "country_code": "NZ", + "region": "Asia-Pacific", + "authority_type": "national_security", + "base_url": "https://safetravel.govt.nz" + }, + "feed_url": "https://safetravel.govt.nz/rss.xml", + "category": "travel_warning", + "region_tag": "NZ", + "lat": -41.29, + "lng": 174.78 + }, + { + "type": "rss", + "source": { + "source_id": "fr-diplomatie-travel", + "authority_name": "France Diplomatie Travel Advice", + "country": "France", + "country_code": "FR", + "region": "Europe", + "authority_type": "national_security", + "base_url": "https://www.diplomatie.gouv.fr" + }, + "feed_url": "https://www.diplomatie.gouv.fr/spip.php?page=backend-fd&lang=fr", + "category": "travel_warning", + "region_tag": "FR", + "lat": 48.86, + "lng": 2.35 + }, + { + "type": "rss", + "source": { + "source_id": "eurojust-news", + "authority_name": "Eurojust Press Releases", + "country": "Netherlands", + "country_code": "NL", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.eurojust.europa.eu" + }, + "feed_url": "https://www.eurojust.europa.eu/rss.xml", + "category": "public_appeal", + "region_tag": "EU", + "lat": 52.09, + "lng": 4.27 + }, + { + "type": "rss", + "source": { + "source_id": "frontex-news", + "authority_name": "Frontex News", + "country": "Poland", + "country_code": "PL", + "region": "Europe", + "authority_type": "national_security", + "base_url": "https://www.frontex.europa.eu" + }, + "feed_url": "https://www.frontex.europa.eu/rss/", + "category": "public_safety", + "region_tag": "EU", + "lat": 52.23, + "lng": 21.01 + }, + { + "type": "rss", + "source": { + "source_id": "dhs-news", + "authority_name": "DHS Press Releases", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "national_security", + "base_url": "https://www.dhs.gov" + }, + "feed_url": "https://www.dhs.gov/news-releases/press-releases/rss.xml", + "category": "public_safety", + "region_tag": "US", + "lat": 38.88, + "lng": -77.02, + "fetch_mode": "browser" + }, + { + "type": "rss", + "source": { + "source_id": "doj-press", + "authority_name": "US DOJ Press Releases", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "national_security", + "base_url": "https://www.justice.gov" + }, + "feed_url": "https://www.justice.gov/feeds/opa/justice-news.xml", + "category": "public_appeal", + "region_tag": "US", + "lat": 38.89, + "lng": -77.02 + }, + { + "type": "rss", + "source": { + "source_id": "fbi-news", + "authority_name": "FBI News", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "police", + "base_url": "https://www.fbi.gov" + }, + "feed_url": "https://www.fbi.gov/feeds/fbi-news-feed/rss.xml", + "category": "public_appeal", + "region_tag": "US", + "lat": 38.89, + "lng": -77.02 + }, + { + "type": "rss", + "source": { + "source_id": "nato-news", + "authority_name": "NATO News", + "country": "Belgium", + "country_code": "BE", + "region": "Europe", + "authority_type": "national_security", + "base_url": "https://www.nato.int" + }, + "feed_url": "https://www.nato.int/cps/en/natolive/news.xml", + "category": "conflict_monitoring", + "region_tag": "INT", + "lat": 50.88, + "lng": 4.43 + }, + { + "type": "rss", + "source": { + "source_id": "un-sc-press", + "authority_name": "UN Security Council Press", + "country": "United States", + "country_code": "US", + "region": "International", + "authority_type": "national_security", + "base_url": "https://www.un.org" + }, + "feed_url": "https://press.un.org/en/un-press-releases/security-council/rss.xml", + "category": "conflict_monitoring", + "region_tag": "INT", + "lat": 40.75, + "lng": -73.97 + }, + { + "type": "rss", + "source": { + "source_id": "osce-news", + "authority_name": "OSCE Press Releases", + "country": "Austria", + "country_code": "AT", + "region": "Europe", + "authority_type": "national_security", + "base_url": "https://www.osce.org" + }, + "feed_url": "https://www.osce.org/rss.xml", + "category": "conflict_monitoring", + "region_tag": "EU", + "lat": 48.21, + "lng": 16.37 + }, + { + "type": "rss", + "source": { + "source_id": "ct-europol", + "authority_name": "Europol Counter-Terrorism", + "country": "Netherlands", + "country_code": "NL", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.europol.europa.eu" + }, + "feed_url": "https://www.europol.europa.eu/taxonomy/term/69/feed", + "category": "terrorism_tip", + "region_tag": "EU", + "lat": 52.09, + "lng": 4.27 + }, + { + "type": "rss", + "source": { + "source_id": "mi5-threats", + "authority_name": "MI5 Threat Assessment", + "country": "United Kingdom", + "country_code": "GB", + "region": "Europe", + "authority_type": "intelligence", + "base_url": "https://www.mi5.gov.uk" + }, + "feed_url": "https://www.mi5.gov.uk/threat-levels.xml", + "category": "terrorism_tip", + "region_tag": "GB", + "lat": 51.5, + "lng": -0.13 + }, + { + "type": "rss", + "source": { + "source_id": "cert-ua", + "authority_name": "CERT-UA", + "country": "Ukraine", + "country_code": "UA", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://cert.gov.ua" + }, + "feed_url": "https://cert.gov.ua/api/articles/rss", + "category": "cyber_advisory", + "region_tag": "UA", + "lat": 50.45, + "lng": 30.52, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "ua-nsdc", + "authority_name": "NSDC Ukraine", + "country": "Ukraine", + "country_code": "UA", + "region": "Europe", + "authority_type": "national_security", + "base_url": "https://www.rnbo.gov.ua" + }, + "feed_url": "https://www.rnbo.gov.ua/en/rss.xml", + "category": "public_safety", + "region_tag": "UA", + "lat": 50.45, + "lng": 30.52 + }, + { + "type": "rss", + "source": { + "source_id": "ua-ssu", + "authority_name": "SBU (Security Service of Ukraine)", + "country": "Ukraine", + "country_code": "UA", + "region": "Europe", + "authority_type": "intelligence", + "base_url": "https://ssu.gov.ua" + }, + "feed_url": "https://ssu.gov.ua/en/rss", + "category": "intelligence_report", + "region_tag": "UA", + "lat": 50.45, + "lng": 30.52 + }, + { + "type": "rss", + "source": { + "source_id": "ua-npu", + "authority_name": "National Police of Ukraine", + "country": "Ukraine", + "country_code": "UA", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.npu.gov.ua" + }, + "feed_url": "https://www.npu.gov.ua/rss", + "category": "public_appeal", + "region_tag": "UA", + "lat": 50.45, + "lng": 30.52 + }, + { + "type": "rss", + "source": { + "source_id": "ru-gov-cert", + "authority_name": "GOV-CERT Russia", + "country": "Russia", + "country_code": "RU", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.gov-cert.ru" + }, + "feed_url": "https://www.gov-cert.ru/rss", + "category": "cyber_advisory", + "region_tag": "RU", + "lat": 55.75, + "lng": 37.62, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "ru-mvd", + "authority_name": "MVD Russia (Interior Ministry)", + "country": "Russia", + "country_code": "RU", + "region": "Europe", + "authority_type": "police", + "base_url": "https://мвд.рф" + }, + "feed_url": "https://мвд.рф/news/feed", + "category": "public_appeal", + "region_tag": "RU", + "lat": 55.75, + "lng": 37.62 + }, + { + "type": "rss", + "source": { + "source_id": "no-pst", + "authority_name": "PST (Norwegian Police Security)", + "country": "Norway", + "country_code": "NO", + "region": "Europe", + "authority_type": "intelligence", + "base_url": "https://www.pst.no" + }, + "feed_url": "https://www.pst.no/rss/", + "category": "intelligence_report", + "region_tag": "NO", + "lat": 59.91, + "lng": 10.75 + }, + { + "type": "rss", + "source": { + "source_id": "no-nsm", + "authority_name": "NSM NorCERT", + "country": "Norway", + "country_code": "NO", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://nsm.no" + }, + "feed_url": "https://nsm.no/aktuelt/feed/", + "category": "cyber_advisory", + "region_tag": "NO", + "lat": 59.91, + "lng": 10.75, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "no-politiet", + "authority_name": "Norwegian Police", + "country": "Norway", + "country_code": "NO", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.politiet.no" + }, + "feed_url": "https://www.politiet.no/rss/", + "category": "public_appeal", + "region_tag": "NO", + "lat": 59.91, + "lng": 10.75 + }, + { + "type": "rss", + "source": { + "source_id": "dk-pet", + "authority_name": "PET (Danish Security Intelligence)", + "country": "Denmark", + "country_code": "DK", + "region": "Europe", + "authority_type": "intelligence", + "base_url": "https://pet.dk" + }, + "feed_url": "https://pet.dk/rss", + "category": "intelligence_report", + "region_tag": "DK", + "lat": 55.68, + "lng": 12.57 + }, + { + "type": "rss", + "source": { + "source_id": "dk-cfcs", + "authority_name": "CFCS (Danish Centre for Cyber Security)", + "country": "Denmark", + "country_code": "DK", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.cfcs.dk" + }, + "feed_url": "https://www.cfcs.dk/da/nyheder/feed/", + "category": "cyber_advisory", + "region_tag": "DK", + "lat": 55.68, + "lng": 12.57, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "dk-politi", + "authority_name": "Danish Police", + "country": "Denmark", + "country_code": "DK", + "region": "Europe", + "authority_type": "police", + "base_url": "https://politi.dk" + }, + "feed_url": "https://politi.dk/rss", + "category": "public_appeal", + "region_tag": "DK", + "lat": 55.68, + "lng": 12.57 + }, + { + "type": "rss", + "source": { + "source_id": "fi-supo", + "authority_name": "SUPO (Finnish Security Intelligence)", + "country": "Finland", + "country_code": "FI", + "region": "Europe", + "authority_type": "intelligence", + "base_url": "https://supo.fi" + }, + "feed_url": "https://supo.fi/en/rss/news", + "category": "intelligence_report", + "region_tag": "FI", + "lat": 60.17, + "lng": 24.94 + }, + { + "type": "rss", + "source": { + "source_id": "fi-ncsc", + "authority_name": "NCSC-FI (Traficom)", + "country": "Finland", + "country_code": "FI", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.kyberturvallisuuskeskus.fi" + }, + "feed_url": "https://www.kyberturvallisuuskeskus.fi/en/rss/news", + "category": "cyber_advisory", + "region_tag": "FI", + "lat": 60.17, + "lng": 24.94, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "fi-poliisi", + "authority_name": "Finnish Police", + "country": "Finland", + "country_code": "FI", + "region": "Europe", + "authority_type": "police", + "base_url": "https://poliisi.fi" + }, + "feed_url": "https://poliisi.fi/en/rss/news", + "category": "public_appeal", + "region_tag": "FI", + "lat": 60.17, + "lng": 24.94 + }, + { + "type": "rss", + "source": { + "source_id": "is-logreglan", + "authority_name": "Icelandic Police", + "country": "Iceland", + "country_code": "IS", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.logreglan.is" + }, + "feed_url": "https://www.logreglan.is/feed/", + "category": "public_appeal", + "region_tag": "IS", + "lat": 64.15, + "lng": -21.94 + }, + { + "type": "rss", + "source": { + "source_id": "pl-abw", + "authority_name": "ABW (Polish Internal Security Agency)", + "country": "Poland", + "country_code": "PL", + "region": "Europe", + "authority_type": "intelligence", + "base_url": "https://www.abw.gov.pl" + }, + "feed_url": "https://www.abw.gov.pl/en/rss", + "category": "intelligence_report", + "region_tag": "PL", + "lat": 52.23, + "lng": 21.01 + }, + { + "type": "rss", + "source": { + "source_id": "pl-policja", + "authority_name": "Polish Police", + "country": "Poland", + "country_code": "PL", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.policja.pl" + }, + "feed_url": "https://www.policja.pl/pol/rss/1,RSS.html", + "category": "public_appeal", + "region_tag": "PL", + "lat": 52.23, + "lng": 21.01 + }, + { + "type": "rss", + "source": { + "source_id": "cz-nukib", + "authority_name": "NUKIB (Czech Cyber Security)", + "country": "Czech Republic", + "country_code": "CZ", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://nukib.gov.cz" + }, + "feed_url": "https://nukib.gov.cz/en/rss/", + "category": "cyber_advisory", + "region_tag": "CZ", + "lat": 50.08, + "lng": 14.42, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "cz-policie", + "authority_name": "Czech Police", + "country": "Czech Republic", + "country_code": "CZ", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.policie.cz" + }, + "feed_url": "https://www.policie.cz/rss/aktuality.aspx", + "category": "public_appeal", + "region_tag": "CZ", + "lat": 50.08, + "lng": 14.42 + }, + { + "type": "rss", + "source": { + "source_id": "hu-police", + "authority_name": "Hungarian Police", + "country": "Hungary", + "country_code": "HU", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.police.hu" + }, + "feed_url": "https://www.police.hu/rss", + "category": "public_appeal", + "region_tag": "HU", + "lat": 47.5, + "lng": 19.04 + }, + { + "type": "rss", + "source": { + "source_id": "ro-politia", + "authority_name": "Romanian Police", + "country": "Romania", + "country_code": "RO", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.politiaromana.ro" + }, + "feed_url": "https://www.politiaromana.ro/ro/rss", + "category": "public_appeal", + "region_tag": "RO", + "lat": 44.43, + "lng": 26.1 + }, + { + "type": "rss", + "source": { + "source_id": "sk-police", + "authority_name": "Slovak Police", + "country": "Slovakia", + "country_code": "SK", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.minv.sk" + }, + "feed_url": "https://www.minv.sk/?rss", + "category": "public_appeal", + "region_tag": "SK", + "lat": 48.15, + "lng": 17.11 + }, + { + "type": "rss", + "source": { + "source_id": "bg-mvr", + "authority_name": "Bulgarian Interior Ministry", + "country": "Bulgaria", + "country_code": "BG", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.mvr.bg" + }, + "feed_url": "https://www.mvr.bg/rss", + "category": "public_appeal", + "region_tag": "BG", + "lat": 42.7, + "lng": 23.32 + }, + { + "type": "rss", + "source": { + "source_id": "rs-mup", + "authority_name": "Serbian Interior Ministry", + "country": "Serbia", + "country_code": "RS", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.mup.gov.rs" + }, + "feed_url": "https://www.mup.gov.rs/wps/rss", + "category": "public_appeal", + "region_tag": "RS", + "lat": 44.79, + "lng": 20.46 + }, + { + "type": "rss", + "source": { + "source_id": "ee-kapo", + "authority_name": "KAPO (Estonian Internal Security)", + "country": "Estonia", + "country_code": "EE", + "region": "Europe", + "authority_type": "intelligence", + "base_url": "https://kapo.ee" + }, + "feed_url": "https://kapo.ee/en/feed", + "category": "intelligence_report", + "region_tag": "EE", + "lat": 59.44, + "lng": 24.75 + }, + { + "type": "rss", + "source": { + "source_id": "lt-vsd", + "authority_name": "VSD (Lithuanian State Security)", + "country": "Lithuania", + "country_code": "LT", + "region": "Europe", + "authority_type": "intelligence", + "base_url": "https://www.vsd.lt" + }, + "feed_url": "https://www.vsd.lt/en/feed/", + "category": "intelligence_report", + "region_tag": "LT", + "lat": 54.69, + "lng": 25.28 + }, + { + "type": "rss", + "source": { + "source_id": "lv-dp", + "authority_name": "Latvian State Police", + "country": "Latvia", + "country_code": "LV", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.vp.gov.lv" + }, + "feed_url": "https://www.vp.gov.lv/lv/rss", + "category": "public_appeal", + "region_tag": "LV", + "lat": 56.95, + "lng": 24.11 + }, + { + "type": "rss", + "source": { + "source_id": "ee-politsei", + "authority_name": "Estonian Police", + "country": "Estonia", + "country_code": "EE", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.politsei.ee" + }, + "feed_url": "https://www.politsei.ee/en/rss", + "category": "public_appeal", + "region_tag": "EE", + "lat": 59.44, + "lng": 24.75 + }, + { + "type": "rss", + "source": { + "source_id": "it-csirt", + "authority_name": "CSIRT Italia", + "country": "Italy", + "country_code": "IT", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.csirt.gov.it" + }, + "feed_url": "https://www.csirt.gov.it/feed/rss", + "category": "cyber_advisory", + "region_tag": "IT", + "lat": 41.9, + "lng": 12.5, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "it-carabinieri", + "authority_name": "Italian Carabinieri", + "country": "Italy", + "country_code": "IT", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.carabinieri.it" + }, + "feed_url": "https://www.carabinieri.it/rss", + "category": "public_appeal", + "region_tag": "IT", + "lat": 41.9, + "lng": 12.5 + }, + { + "type": "rss", + "source": { + "source_id": "gr-police", + "authority_name": "Hellenic Police", + "country": "Greece", + "country_code": "GR", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.astynomia.gr" + }, + "feed_url": "https://www.astynomia.gr/rss", + "category": "public_appeal", + "region_tag": "GR", + "lat": 37.98, + "lng": 23.73 + }, + { + "type": "rss", + "source": { + "source_id": "pt-cncs", + "authority_name": "CNCS (CERT Portugal)", + "country": "Portugal", + "country_code": "PT", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.cncs.gov.pt" + }, + "feed_url": "https://www.cncs.gov.pt/pt/feed/", + "category": "cyber_advisory", + "region_tag": "PT", + "lat": 38.72, + "lng": -9.14, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "ch-ncsc", + "authority_name": "Swiss NCSC", + "country": "Switzerland", + "country_code": "CH", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.ncsc.admin.ch" + }, + "feed_url": "https://www.ncsc.admin.ch/ncsc/en/home.rss", + "category": "cyber_advisory", + "region_tag": "CH", + "lat": 46.95, + "lng": 7.45, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "ch-fedpol", + "authority_name": "Swiss Federal Police (fedpol)", + "country": "Switzerland", + "country_code": "CH", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.fedpol.admin.ch" + }, + "feed_url": "https://www.fedpol.admin.ch/fedpol/en/home.rss", + "category": "public_appeal", + "region_tag": "CH", + "lat": 46.95, + "lng": 7.45 + }, + { + "type": "rss", + "source": { + "source_id": "at-bmi", + "authority_name": "Austrian Interior Ministry", + "country": "Austria", + "country_code": "AT", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.bmi.gv.at" + }, + "feed_url": "https://www.bmi.gv.at/rss", + "category": "public_appeal", + "region_tag": "AT", + "lat": 48.21, + "lng": 16.37 + }, + { + "type": "rss", + "source": { + "source_id": "ie-ncsc", + "authority_name": "NCSC Ireland", + "country": "Ireland", + "country_code": "IE", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://www.ncsc.gov.ie" + }, + "feed_url": "https://www.ncsc.gov.ie/news/rss.php", + "category": "cyber_advisory", + "region_tag": "IE", + "lat": 53.35, + "lng": -6.26, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "no-ud-travel", + "authority_name": "Norway MFA Travel Advice", + "country": "Norway", + "country_code": "NO", + "region": "Europe", + "authority_type": "national_security", + "base_url": "https://www.regjeringen.no" + }, + "feed_url": "https://www.regjeringen.no/en/topics/foreign-affairs/rss/", + "category": "travel_warning", + "region_tag": "NO", + "lat": 59.91, + "lng": 10.75 + }, + { + "type": "rss", + "source": { + "source_id": "dk-um-travel", + "authority_name": "Denmark MFA Travel Advice", + "country": "Denmark", + "country_code": "DK", + "region": "Europe", + "authority_type": "national_security", + "base_url": "https://um.dk" + }, + "feed_url": "https://um.dk/en/rss", + "category": "travel_warning", + "region_tag": "DK", + "lat": 55.68, + "lng": 12.57 + }, + { + "type": "rss", + "source": { + "source_id": "fi-um-travel", + "authority_name": "Finland MFA Travel Advice", + "country": "Finland", + "country_code": "FI", + "region": "Europe", + "authority_type": "national_security", + "base_url": "https://um.fi" + }, + "feed_url": "https://um.fi/rss/en/travel-advisories", + "category": "travel_warning", + "region_tag": "FI", + "lat": 60.17, + "lng": 24.94 + }, + { + "type": "rss", + "source": { + "source_id": "se-ud-travel", + "authority_name": "Sweden MFA Travel Advice", + "country": "Sweden", + "country_code": "SE", + "region": "Europe", + "authority_type": "national_security", + "base_url": "https://www.government.se" + }, + "feed_url": "https://www.government.se/rss/travel-advisories/", + "category": "travel_warning", + "region_tag": "SE", + "lat": 59.33, + "lng": 18.07 + }, + { + "type": "rss", + "source": { + "source_id": "nl-bz-travel", + "authority_name": "Netherlands MFA Travel Advice", + "country": "Netherlands", + "country_code": "NL", + "region": "Europe", + "authority_type": "national_security", + "base_url": "https://www.netherlandsworldwide.nl" + }, + "feed_url": "https://www.netherlandsworldwide.nl/rss/travel-advisories", + "category": "travel_warning", + "region_tag": "NL", + "lat": 52.08, + "lng": 4.31 + }, + { + "type": "rss", + "source": { + "source_id": "ie-dfa-travel", + "authority_name": "Ireland DFA Travel Advice", + "country": "Ireland", + "country_code": "IE", + "region": "Europe", + "authority_type": "national_security", + "base_url": "https://www.ireland.ie" + }, + "feed_url": "https://www.ireland.ie/en/dfa/overseas-travel/rss/", + "category": "travel_warning", + "region_tag": "IE", + "lat": 53.35, + "lng": -6.26 + }, + { + "type": "rss", + "source": { + "source_id": "at-bmeia-travel", + "authority_name": "Austria MFA Travel Advice", + "country": "Austria", + "country_code": "AT", + "region": "Europe", + "authority_type": "national_security", + "base_url": "https://www.bmeia.gv.at" + }, + "feed_url": "https://www.bmeia.gv.at/reise-services/reiseinformation/rss/", + "category": "travel_warning", + "region_tag": "AT", + "lat": 48.21, + "lng": 16.37 + }, + { + "type": "rss", + "source": { + "source_id": "ch-eda-travel", + "authority_name": "Switzerland FDFA Travel Advice", + "country": "Switzerland", + "country_code": "CH", + "region": "Europe", + "authority_type": "national_security", + "base_url": "https://www.eda.admin.ch" + }, + "feed_url": "https://www.eda.admin.ch/eda/en/fdfa/representations-and-travel-advice.rss", + "category": "travel_warning", + "region_tag": "CH", + "lat": 46.95, + "lng": 7.45 + }, + { + "type": "rss", + "source": { + "source_id": "it-farnesina-travel", + "authority_name": "Italy Farnesina Travel Advice", + "country": "Italy", + "country_code": "IT", + "region": "Europe", + "authority_type": "national_security", + "base_url": "https://www.viaggiaresicuri.it" + }, + "feed_url": "https://www.viaggiaresicuri.it/rss", + "category": "travel_warning", + "region_tag": "IT", + "lat": 41.9, + "lng": 12.5 + }, + { + "type": "rss", + "source": { + "source_id": "jp-mofa-travel", + "authority_name": "Japan MOFA Travel Safety", + "country": "Japan", + "country_code": "JP", + "region": "Asia-Pacific", + "authority_type": "national_security", + "base_url": "https://www.anzen.mofa.go.jp" + }, + "feed_url": "https://www.anzen.mofa.go.jp/rss/rss.xml", + "category": "travel_warning", + "region_tag": "JP", + "lat": 35.68, + "lng": 139.77 + }, + { + "type": "rss", + "source": { + "source_id": "ge-ssg", + "authority_name": "Georgian State Security Service", + "country": "Georgia", + "country_code": "GE", + "region": "Europe", + "authority_type": "intelligence", + "base_url": "https://ssg.gov.ge" + }, + "feed_url": "https://ssg.gov.ge/en/feed", + "category": "intelligence_report", + "region_tag": "GE", + "lat": 41.69, + "lng": 44.8 + }, + { + "type": "rss", + "source": { + "source_id": "md-sis", + "authority_name": "Moldova SIS (Intelligence & Security)", + "country": "Moldova", + "country_code": "MD", + "region": "Europe", + "authority_type": "intelligence", + "base_url": "https://www.sis.md" + }, + "feed_url": "https://www.sis.md/en/rss", + "category": "intelligence_report", + "region_tag": "MD", + "lat": 47.01, + "lng": 28.86 + }, + { + "type": "rss", + "source": { + "source_id": "mt-police", + "authority_name": "Malta Police Force", + "country": "Malta", + "country_code": "MT", + "region": "Europe", + "authority_type": "police", + "base_url": "https://pulizija.gov.mt" + }, + "feed_url": "https://pulizija.gov.mt/en/feed/", + "category": "public_appeal", + "region_tag": "MT", + "lat": 35.9, + "lng": 14.51 + }, + { + "type": "rss", + "source": { + "source_id": "mt-mfsa", + "authority_name": "Malta Financial Services Authority", + "country": "Malta", + "country_code": "MT", + "region": "Europe", + "authority_type": "regulatory", + "base_url": "https://www.mfsa.mt" + }, + "feed_url": "https://www.mfsa.mt/feed/", + "category": "fraud_alert", + "region_tag": "MT", + "lat": 35.9, + "lng": 14.51 + }, + { + "type": "rss", + "source": { + "source_id": "cy-police", + "authority_name": "Cyprus Police", + "country": "Cyprus", + "country_code": "CY", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.police.gov.cy" + }, + "feed_url": "https://www.police.gov.cy/police/police.nsf/rss.xml", + "category": "public_appeal", + "region_tag": "CY", + "lat": 35.17, + "lng": 33.36 + }, + { + "type": "rss", + "source": { + "source_id": "cy-csirt", + "authority_name": "CSIRT Cyprus", + "country": "Cyprus", + "country_code": "CY", + "region": "Europe", + "authority_type": "cert", + "base_url": "https://csirt.cy" + }, + "feed_url": "https://csirt.cy/en/feed/", + "category": "cyber_advisory", + "region_tag": "CY", + "lat": 35.17, + "lng": 33.36, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "si-police", + "authority_name": "Slovenian Police", + "country": "Slovenia", + "country_code": "SI", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.policija.si" + }, + "feed_url": "https://www.policija.si/eng/rss", + "category": "public_appeal", + "region_tag": "SI", + "lat": 46.06, + "lng": 14.51 + }, + { + "type": "rss", + "source": { + "source_id": "il-shin-bet", + "authority_name": "Israel Security Agency (Shin Bet)", + "country": "Israel", + "country_code": "IL", + "region": "Middle East", + "authority_type": "intelligence", + "base_url": "https://www.shabak.gov.il" + }, + "feed_url": "https://www.shabak.gov.il/en/rss", + "category": "intelligence_report", + "region_tag": "IL", + "lat": 31.77, + "lng": 35.22 + }, + { + "type": "rss", + "source": { + "source_id": "il-cert", + "authority_name": "Israel CERT (INCD)", + "country": "Israel", + "country_code": "IL", + "region": "Middle East", + "authority_type": "cert", + "base_url": "https://www.gov.il/en/departments/israel_national_cyber_directorate" + }, + "feed_url": "https://www.gov.il/he/api/DataGovProxy/GetDGResults?CatalogId=cybernews&Limit=20&Offset=0", + "category": "cyber_advisory", + "region_tag": "IL", + "lat": 32.07, + "lng": 34.78, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "ae-cert", + "authority_name": "UAE aeCERT", + "country": "United Arab Emirates", + "country_code": "AE", + "region": "Middle East", + "authority_type": "cert", + "base_url": "https://www.tra.gov.ae" + }, + "feed_url": "https://www.tra.gov.ae/aecert/en/rss.xml", + "category": "cyber_advisory", + "region_tag": "AE", + "lat": 24.45, + "lng": 54.65, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "sa-cert", + "authority_name": "Saudi CERT (NCA)", + "country": "Saudi Arabia", + "country_code": "SA", + "region": "Middle East", + "authority_type": "cert", + "base_url": "https://cert.gov.sa" + }, + "feed_url": "https://cert.gov.sa/en/rss/", + "category": "cyber_advisory", + "region_tag": "SA", + "lat": 24.71, + "lng": 46.68, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "jo-ncsc", + "authority_name": "Jordan NCSC", + "country": "Jordan", + "country_code": "JO", + "region": "Middle East", + "authority_type": "cert", + "base_url": "https://www.ncsc.jo" + }, + "feed_url": "https://www.ncsc.jo/en/feed", + "category": "cyber_advisory", + "region_tag": "JO", + "lat": 31.95, + "lng": 35.93, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "qa-ncsa", + "authority_name": "Qatar NCSA", + "country": "Qatar", + "country_code": "QA", + "region": "Middle East", + "authority_type": "cert", + "base_url": "https://www.ncsa.gov.qa" + }, + "feed_url": "https://www.ncsa.gov.qa/en/rss", + "category": "cyber_advisory", + "region_tag": "QA", + "lat": 25.29, + "lng": 51.53, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "au-african-union", + "authority_name": "African Union Peace & Security", + "country": "Ethiopia", + "country_code": "ET", + "region": "Africa", + "authority_type": "national_security", + "base_url": "https://www.peaceau.org" + }, + "feed_url": "https://www.peaceau.org/rss/en/feed.xml", + "category": "conflict_monitoring", + "region_tag": "INT", + "lat": 9.02, + "lng": 38.75 + }, + { + "type": "rss", + "source": { + "source_id": "eg-cert", + "authority_name": "Egypt CERT (EG-CERT)", + "country": "Egypt", + "country_code": "EG", + "region": "Africa", + "authority_type": "cert", + "base_url": "https://www.egcert.eg" + }, + "feed_url": "https://www.egcert.eg/feed/", + "category": "cyber_advisory", + "region_tag": "EG", + "lat": 30.04, + "lng": 31.24, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "ma-dgssi", + "authority_name": "Morocco DGSSI (maCERT)", + "country": "Morocco", + "country_code": "MA", + "region": "Africa", + "authority_type": "cert", + "base_url": "https://www.dgssi.gov.ma" + }, + "feed_url": "https://www.dgssi.gov.ma/fr/feed", + "category": "cyber_advisory", + "region_tag": "MA", + "lat": 33.97, + "lng": -6.85, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "rw-police", + "authority_name": "Rwanda National Police", + "country": "Rwanda", + "country_code": "RW", + "region": "Africa", + "authority_type": "police", + "base_url": "https://www.police.gov.rw" + }, + "feed_url": "https://www.police.gov.rw/rss/", + "category": "public_appeal", + "region_tag": "RW", + "lat": -1.94, + "lng": 29.87 + }, + { + "type": "rss", + "source": { + "source_id": "et-insa", + "authority_name": "Ethiopia INSA (Cyber Security)", + "country": "Ethiopia", + "country_code": "ET", + "region": "Africa", + "authority_type": "cert", + "base_url": "https://www.insa.gov.et" + }, + "feed_url": "https://www.insa.gov.et/feed/", + "category": "cyber_advisory", + "region_tag": "ET", + "lat": 9.02, + "lng": 38.75, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "sn-police", + "authority_name": "Senegal Police Nationale", + "country": "Senegal", + "country_code": "SN", + "region": "Africa", + "authority_type": "police", + "base_url": "https://www.police.gouv.sn" + }, + "feed_url": "https://www.police.gouv.sn/feed/", + "category": "public_appeal", + "region_tag": "SN", + "lat": 14.69, + "lng": -17.44 + }, + { + "type": "rss", + "source": { + "source_id": "dz-cert", + "authority_name": "Algeria CERT (DZ-CERT)", + "country": "Algeria", + "country_code": "DZ", + "region": "Africa", + "authority_type": "cert", + "base_url": "https://www.cert.dz" + }, + "feed_url": "https://www.cert.dz/feed", + "category": "cyber_advisory", + "region_tag": "DZ", + "lat": 36.74, + "lng": 3.06, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "tw-cert", + "authority_name": "Taiwan CERT (TWCERT/CC)", + "country": "Taiwan", + "country_code": "TW", + "region": "Asia", + "authority_type": "cert", + "base_url": "https://www.twcert.org.tw" + }, + "feed_url": "https://www.twcert.org.tw/en/rss/", + "category": "cyber_advisory", + "region_tag": "TW", + "lat": 25.03, + "lng": 121.57, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "cn-cert", + "authority_name": "CNCERT/CC (China CERT)", + "country": "China", + "country_code": "CN", + "region": "Asia", + "authority_type": "cert", + "base_url": "https://www.cert.org.cn" + }, + "feed_url": "https://www.cert.org.cn/publish/english/rss.xml", + "category": "cyber_advisory", + "region_tag": "CN", + "lat": 39.91, + "lng": 116.4, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "vn-cert", + "authority_name": "VNCERT/CC (Vietnam CERT)", + "country": "Vietnam", + "country_code": "VN", + "region": "Asia", + "authority_type": "cert", + "base_url": "https://vncert.vn" + }, + "feed_url": "https://vncert.vn/feed/", + "category": "cyber_advisory", + "region_tag": "VN", + "lat": 21.03, + "lng": 105.85, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "pk-cert", + "authority_name": "Pakistan CERT (PkCERT)", + "country": "Pakistan", + "country_code": "PK", + "region": "Asia", + "authority_type": "cert", + "base_url": "https://www.pkcert.org.pk" + }, + "feed_url": "https://www.pkcert.org.pk/feed/", + "category": "cyber_advisory", + "region_tag": "PK", + "lat": 33.69, + "lng": 73.04, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "bd-cert", + "authority_name": "BGD e-GOV CIRT (Bangladesh)", + "country": "Bangladesh", + "country_code": "BD", + "region": "Asia", + "authority_type": "cert", + "base_url": "https://www.cirt.gov.bd" + }, + "feed_url": "https://www.cirt.gov.bd/feed/", + "category": "cyber_advisory", + "region_tag": "BD", + "lat": 23.81, + "lng": 90.41, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "lk-cert", + "authority_name": "Sri Lanka CERT", + "country": "Sri Lanka", + "country_code": "LK", + "region": "Asia", + "authority_type": "cert", + "base_url": "https://www.cert.gov.lk" + }, + "feed_url": "https://www.cert.gov.lk/feed/", + "category": "cyber_advisory", + "region_tag": "LK", + "lat": 6.93, + "lng": 79.85, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "mn-cert", + "authority_name": "Mongolia CERT (MonCIRT)", + "country": "Mongolia", + "country_code": "MN", + "region": "Asia", + "authority_type": "cert", + "base_url": "https://www.moncirt.org.mn" + }, + "feed_url": "https://www.moncirt.org.mn/feed/", + "category": "cyber_advisory", + "region_tag": "MN", + "lat": 47.92, + "lng": 106.91, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "aseanapol", + "authority_name": "ASEANAPOL (ASEAN Police)", + "country": "Singapore", + "country_code": "SG", + "region": "Asia", + "authority_type": "police", + "base_url": "https://www.aseanapol.org" + }, + "feed_url": "https://www.aseanapol.org/feed/", + "category": "public_appeal", + "region_tag": "INT", + "lat": 1.35, + "lng": 103.82 + }, + { + "type": "rss", + "source": { + "source_id": "apcert", + "authority_name": "APCERT (Asia-Pacific CERT)", + "country": "Japan", + "country_code": "JP", + "region": "Asia-Pacific", + "authority_type": "cert", + "base_url": "https://www.apcert.org" + }, + "feed_url": "https://www.apcert.org/feed/", + "category": "cyber_advisory", + "region_tag": "INT", + "lat": 35.68, + "lng": 139.77, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "au-afp", + "authority_name": "Australian Federal Police", + "country": "Australia", + "country_code": "AU", + "region": "Oceania", + "authority_type": "police", + "base_url": "https://www.afp.gov.au" + }, + "feed_url": "https://www.afp.gov.au/rss.xml", + "category": "public_appeal", + "region_tag": "AU", + "lat": -35.28, + "lng": 149.13 + }, + { + "type": "rss", + "source": { + "source_id": "au-acsc", + "authority_name": "Australian Cyber Security Centre", + "country": "Australia", + "country_code": "AU", + "region": "Oceania", + "authority_type": "cert", + "base_url": "https://www.cyber.gov.au" + }, + "feed_url": "https://www.cyber.gov.au/rss.xml", + "category": "cyber_advisory", + "region_tag": "AU", + "lat": -35.28, + "lng": 149.13, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "ar-cert", + "authority_name": "Argentina CERT (ICIC-CERT)", + "country": "Argentina", + "country_code": "AR", + "region": "South America", + "authority_type": "cert", + "base_url": "https://www.argentina.gob.ar/jefatura/innovacion-publica/ssetic/direccion-nacional-ciberseguridad/cert" + }, + "feed_url": "https://www.argentina.gob.ar/jefatura/innovacion-publica/ssetic/direccion-nacional-ciberseguridad/cert/rss", + "category": "cyber_advisory", + "region_tag": "AR", + "lat": -34.6, + "lng": -58.38, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "br-cert", + "authority_name": "CERT.br (Brazil CERT)", + "country": "Brazil", + "country_code": "BR", + "region": "South America", + "authority_type": "cert", + "base_url": "https://www.cert.br" + }, + "feed_url": "https://www.cert.br/rss/certbr-rss.xml", + "category": "cyber_advisory", + "region_tag": "BR", + "lat": -23.55, + "lng": -46.63, + "max_items": 15 + }, + { + "type": "rss", + "source": { + "source_id": "ofac-sdn", + "authority_name": "US Treasury OFAC Sanctions", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "national_security", + "base_url": "https://www.treasury.gov" + }, + "feed_url": "https://ofac.treasury.gov/system/files/126/sdn.xml", + "category": "fraud_alert", + "region_tag": "US", + "lat": 38.89, + "lng": -77.03 + }, + { + "type": "rss", + "source": { + "source_id": "ofac-updates", + "authority_name": "OFAC Recent Actions", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "national_security", + "base_url": "https://ofac.treasury.gov" + }, + "feed_url": "https://ofac.treasury.gov/recent-actions/rss.xml", + "category": "fraud_alert", + "region_tag": "US", + "lat": 38.89, + "lng": -77.03 + }, + { + "type": "rss", + "source": { + "source_id": "eu-sanctions", + "authority_name": "EU Sanctions Map", + "country": "Belgium", + "country_code": "BE", + "region": "Europe", + "authority_type": "national_security", + "base_url": "https://www.sanctionsmap.eu" + }, + "feed_url": "https://webgate.ec.europa.eu/fsd/fsf/public/rss/feed", + "category": "fraud_alert", + "region_tag": "EU", + "lat": 50.85, + "lng": 4.35 + }, + { + "type": "rss", + "source": { + "source_id": "un-sanctions", + "authority_name": "UN Security Council Sanctions", + "country": "United States", + "country_code": "US", + "region": "International", + "authority_type": "national_security", + "base_url": "https://www.un.org/securitycouncil/sanctions" + }, + "feed_url": "https://scsanctions.un.org/resources/xml/en/consolidated.xml", + "category": "fraud_alert", + "region_tag": "INT", + "lat": 40.75, + "lng": -73.97 + }, + { + "type": "rss", + "source": { + "source_id": "fatf-updates", + "authority_name": "FATF (Financial Action Task Force)", + "country": "France", + "country_code": "FR", + "region": "International", + "authority_type": "regulatory", + "base_url": "https://www.fatf-gafi.org" + }, + "feed_url": "https://www.fatf-gafi.org/rss/publications.xml", + "category": "fraud_alert", + "region_tag": "INT", + "lat": 48.86, + "lng": 2.33 + }, + { + "type": "rss", + "source": { + "source_id": "opensanctions", + "authority_name": "OpenSanctions", + "country": "Global", + "country_code": "INT", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://www.opensanctions.org" + }, + "feed_url": "https://www.opensanctions.org/rss/index.xml", + "category": "fraud_alert", + "region_tag": "INT", + "lat": 52.52, + "lng": 13.41 + }, + { + "type": "rss", + "source": { + "source_id": "fca-warnings", + "authority_name": "FCA Consumer Warnings", + "country": "United Kingdom", + "country_code": "GB", + "region": "Europe", + "authority_type": "regulatory", + "base_url": "https://www.fca.org.uk" + }, + "feed_url": "https://www.fca.org.uk/news/rss.xml", + "category": "fraud_alert", + "region_tag": "GB", + "lat": 51.51, + "lng": -0.09 + }, + { + "type": "rss", + "source": { + "source_id": "bafin-warnings", + "authority_name": "BaFin Unauthorized Firms", + "country": "Germany", + "country_code": "DE", + "region": "Europe", + "authority_type": "regulatory", + "base_url": "https://www.bafin.de" + }, + "feed_url": "https://www.bafin.de/SiteGlobals/Functions/RSSFeed/EN/RSSVerbraucherschutz/RSSVerbraucherschutz.xml", + "category": "fraud_alert", + "region_tag": "DE", + "lat": 50.11, + "lng": 8.68 + }, + { + "type": "rss", + "source": { + "source_id": "esma-warnings", + "authority_name": "ESMA Investor Warnings", + "country": "France", + "country_code": "FR", + "region": "Europe", + "authority_type": "regulatory", + "base_url": "https://www.esma.europa.eu" + }, + "feed_url": "https://www.esma.europa.eu/rss.xml", + "category": "fraud_alert", + "region_tag": "EU", + "lat": 48.86, + "lng": 2.33 + }, + { + "type": "rss", + "source": { + "source_id": "sec-enforcement", + "authority_name": "SEC Enforcement Actions", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "regulatory", + "base_url": "https://www.sec.gov" + }, + "feed_url": "https://www.sec.gov/rss/litigation/litreleases.xml", + "category": "fraud_alert", + "region_tag": "US", + "lat": 38.9, + "lng": -77.04 + }, + { + "type": "rss", + "source": { + "source_id": "sec-alerts", + "authority_name": "SEC Investor Alerts", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "regulatory", + "base_url": "https://www.sec.gov" + }, + "feed_url": "https://www.sec.gov/rss/investor_alerts.xml", + "category": "fraud_alert", + "region_tag": "US", + "lat": 38.9, + "lng": -77.04 + }, + { + "type": "rss", + "source": { + "source_id": "fincen-advisories", + "authority_name": "FinCEN Advisories", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "regulatory", + "base_url": "https://www.fincen.gov" + }, + "feed_url": "https://www.fincen.gov/rss/advisories.xml", + "category": "fraud_alert", + "region_tag": "US", + "lat": 38.88, + "lng": -77.17 + }, + { + "type": "rss", + "source": { + "source_id": "finma-warnings", + "authority_name": "FINMA Warnings (Switzerland)", + "country": "Switzerland", + "country_code": "CH", + "region": "Europe", + "authority_type": "regulatory", + "base_url": "https://www.finma.ch" + }, + "feed_url": "https://www.finma.ch/en/rss/finma-news/", + "category": "fraud_alert", + "region_tag": "CH", + "lat": 46.95, + "lng": 7.45 + }, + { + "type": "rss", + "source": { + "source_id": "amf-warnings", + "authority_name": "AMF Blacklists (France)", + "country": "France", + "country_code": "FR", + "region": "Europe", + "authority_type": "regulatory", + "base_url": "https://www.amf-france.org" + }, + "feed_url": "https://www.amf-france.org/en/rss", + "category": "fraud_alert", + "region_tag": "FR", + "lat": 48.86, + "lng": 2.33 + }, + { + "type": "rss", + "source": { + "source_id": "consob-warnings", + "authority_name": "CONSOB Investor Warnings (Italy)", + "country": "Italy", + "country_code": "IT", + "region": "Europe", + "authority_type": "regulatory", + "base_url": "https://www.consob.it" + }, + "feed_url": "https://www.consob.it/web/consob-en/rss-feed", + "category": "fraud_alert", + "region_tag": "IT", + "lat": 41.9, + "lng": 12.5 + }, + { + "type": "rss", + "source": { + "source_id": "cnmv-warnings", + "authority_name": "CNMV Investor Warnings (Spain)", + "country": "Spain", + "country_code": "ES", + "region": "Europe", + "authority_type": "regulatory", + "base_url": "https://www.cnmv.es" + }, + "feed_url": "https://www.cnmv.es/Portal/rss.aspx?lang=en", + "category": "fraud_alert", + "region_tag": "ES", + "lat": 40.42, + "lng": -3.7 + }, + { + "type": "rss", + "source": { + "source_id": "afm-nl-warnings", + "authority_name": "AFM Warnings (Netherlands)", + "country": "Netherlands", + "country_code": "NL", + "region": "Europe", + "authority_type": "regulatory", + "base_url": "https://www.afm.nl" + }, + "feed_url": "https://www.afm.nl/en/rss/all", + "category": "fraud_alert", + "region_tag": "NL", + "lat": 52.37, + "lng": 4.89 + }, + { + "type": "rss", + "source": { + "source_id": "dnb-nl-warnings", + "authority_name": "DNB Warnings (Dutch Central Bank)", + "country": "Netherlands", + "country_code": "NL", + "region": "Europe", + "authority_type": "regulatory", + "base_url": "https://www.dnb.nl" + }, + "feed_url": "https://www.dnb.nl/en/rss/", + "category": "fraud_alert", + "region_tag": "NL", + "lat": 52.37, + "lng": 4.89 + }, + { + "type": "rss", + "source": { + "source_id": "ecb-press", + "authority_name": "ECB Press Releases", + "country": "Germany", + "country_code": "DE", + "region": "Europe", + "authority_type": "regulatory", + "base_url": "https://www.ecb.europa.eu" + }, + "feed_url": "https://www.ecb.europa.eu/rss/press.html", + "category": "fraud_alert", + "region_tag": "EU", + "lat": 50.11, + "lng": 8.68 + }, + { + "type": "rss", + "source": { + "source_id": "occrp-investigations", + "authority_name": "OCCRP Investigations", + "country": "Bosnia and Herzegovina", + "country_code": "BA", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://www.occrp.org" + }, + "feed_url": "https://www.occrp.org/en/rss", + "category": "fraud_alert", + "region_tag": "INT", + "lat": 43.86, + "lng": 18.41 + }, + { + "type": "rss", + "source": { + "source_id": "transparency-intl", + "authority_name": "Transparency International", + "country": "Germany", + "country_code": "DE", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://www.transparency.org" + }, + "feed_url": "https://www.transparency.org/en/rss", + "category": "fraud_alert", + "region_tag": "INT", + "lat": 52.52, + "lng": 13.38 + }, + { + "type": "rss", + "source": { + "source_id": "unodc-news", + "authority_name": "UNODC (UN Office on Drugs & Crime)", + "country": "Austria", + "country_code": "AT", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://www.unodc.org" + }, + "feed_url": "https://www.unodc.org/rss/press.xml", + "category": "public_safety", + "region_tag": "INT", + "lat": 48.24, + "lng": 16.41 + }, + { + "type": "rss", + "source": { + "source_id": "eu-enfast", + "authority_name": "EU Most Wanted (ENFAST)", + "country": "Netherlands", + "country_code": "NL", + "region": "Europe", + "authority_type": "police", + "base_url": "https://eumostwanted.eu" + }, + "feed_url": "https://eumostwanted.eu/rss.xml", + "category": "wanted_suspect", + "region_tag": "EU", + "lat": 52.09, + "lng": 4.27 + }, + { + "type": "rss", + "source": { + "source_id": "dia-it", + "authority_name": "DIA Anti-Mafia (Italy)", + "country": "Italy", + "country_code": "IT", + "region": "Europe", + "authority_type": "police", + "base_url": "https://direzioneinvestigativaantimafia.interno.gov.it" + }, + "feed_url": "https://direzioneinvestigativaantimafia.interno.gov.it/feed/", + "category": "public_appeal", + "region_tag": "IT", + "lat": 41.9, + "lng": 12.5 + }, + { + "type": "rss", + "source": { + "source_id": "gdf-it", + "authority_name": "Guardia di Finanza (Italy)", + "country": "Italy", + "country_code": "IT", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.gdf.gov.it" + }, + "feed_url": "https://www.gdf.gov.it/it/rss", + "category": "fraud_alert", + "region_tag": "IT", + "lat": 41.9, + "lng": 12.5 + }, + { + "type": "rss", + "source": { + "source_id": "sfo-uk", + "authority_name": "Serious Fraud Office (UK)", + "country": "United Kingdom", + "country_code": "GB", + "region": "Europe", + "authority_type": "police", + "base_url": "https://www.sfo.gov.uk" + }, + "feed_url": "https://www.sfo.gov.uk/feed/", + "category": "fraud_alert", + "region_tag": "GB", + "lat": 51.51, + "lng": -0.1 + }, + { + "type": "rss", + "source": { + "source_id": "olaf-eu", + "authority_name": "OLAF (EU Anti-Fraud Office)", + "country": "Belgium", + "country_code": "BE", + "region": "Europe", + "authority_type": "regulatory", + "base_url": "https://anti-fraud.ec.europa.eu" + }, + "feed_url": "https://anti-fraud.ec.europa.eu/rss_en", + "category": "fraud_alert", + "region_tag": "EU", + "lat": 50.84, + "lng": 4.37 + }, + { + "type": "rss", + "source": { + "source_id": "eppo-eu", + "authority_name": "EPPO (EU Public Prosecutor)", + "country": "Luxembourg", + "country_code": "LU", + "region": "Europe", + "authority_type": "regulatory", + "base_url": "https://www.eppo.europa.eu" + }, + "feed_url": "https://www.eppo.europa.eu/en/rss.xml", + "category": "fraud_alert", + "region_tag": "EU", + "lat": 49.61, + "lng": 6.13 + }, + { + "type": "rss", + "source": { + "source_id": "dea-press", + "authority_name": "DEA Press Releases", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "police", + "base_url": "https://www.dea.gov" + }, + "feed_url": "https://www.dea.gov/rss/press-releases.xml", + "category": "public_appeal", + "region_tag": "US", + "lat": 38.87, + "lng": -77.14 + }, + { + "type": "rss", + "source": { + "source_id": "atf-press", + "authority_name": "ATF Press Releases", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "police", + "base_url": "https://www.atf.gov" + }, + "feed_url": "https://www.atf.gov/rss/news", + "category": "public_appeal", + "region_tag": "US", + "lat": 38.89, + "lng": -77.02 + }, + { + "type": "rss", + "source": { + "source_id": "ic3-fbi", + "authority_name": "FBI IC3 (Internet Crime Complaint Center)", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "police", + "base_url": "https://www.ic3.gov" + }, + "feed_url": "https://www.ic3.gov/Home/RSS", + "category": "fraud_alert", + "region_tag": "US", + "lat": 39.29, + "lng": -76.61 } ] From 06c1ba4f55521229c7c1b646de7e04bec9109760 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 18:15:57 +0100 Subject: [PATCH 11/58] feat(sourcedb): add FTS5 search index for alerts Alerts table now has a companion alerts_fts virtual table with BM25 ranking. SearchAlerts method supports text queries, category/region/ status filters, and automatic FTS index rebuild on SaveAlerts. --- internal/sourcedb/db.go | 119 +++++++++++++++++++++++++++++++++++ internal/sourcedb/schema.sql | 12 ++++ 2 files changed, 131 insertions(+) diff --git a/internal/sourcedb/db.go b/internal/sourcedb/db.go index e610d82..b51dc14 100644 --- a/internal/sourcedb/db.go +++ b/internal/sourcedb/db.go @@ -575,12 +575,131 @@ ON CONFLICT(alert_id) DO UPDATE SET return fmt.Errorf("upsert alert %s: %w", alert.AlertID, err) } } + // Rebuild FTS index. + if _, err := tx.ExecContext(ctx, `DELETE FROM alerts_fts`); err != nil { + return fmt.Errorf("clear alerts_fts: %w", err) + } + if _, err := tx.ExecContext(ctx, ` +INSERT INTO alerts_fts (alert_id, title, canonical_url, category, severity, region_tag, + source_authority, source_country, source_country_code) +SELECT a.alert_id, a.title, a.canonical_url, a.category, a.severity, a.region_tag, + json_extract(a.source_json, '$.authority_name'), + json_extract(a.source_json, '$.country'), + json_extract(a.source_json, '$.country_code') +FROM alerts a +`); err != nil { + return fmt.Errorf("rebuild alerts_fts: %w", err) + } + if err := tx.Commit(); err != nil { return fmt.Errorf("commit alert save tx: %w", err) } return nil } +// SearchAlerts performs full-text search against the alerts FTS index. +// The query supports FTS5 syntax: bare words, "quoted phrases", prefix*, AND/OR/NOT. +// Results are ordered by BM25 relevance. Limit 0 means default (100). +func (db *DB) SearchAlerts(ctx context.Context, query string, category string, region string, status string, limit int) ([]model.Alert, error) { + if limit <= 0 { + limit = 100 + } + + query = strings.TrimSpace(query) + if query == "" && category == "" && region == "" { + return nil, nil + } + + var ( + rows *sql.Rows + err error + ) + if query != "" { + // FTS5 match with optional filters on the joined alerts table. + where := `WHERE alerts_fts MATCH ?` + args := []any{query} + if category != "" { + where += ` AND a.category = ?` + args = append(args, category) + } + if region != "" { + where += ` AND a.region_tag = ?` + args = append(args, region) + } + if status != "" { + where += ` AND a.status = ?` + args = append(args, status) + } + args = append(args, limit) + rows, err = db.sql.QueryContext(ctx, ` +SELECT a.alert_id, a.source_id, a.status, a.first_seen, a.last_seen, a.title, + a.canonical_url, a.category, a.severity, a.region_tag, a.lat, a.lng, + a.freshness_hours, a.source_json, a.reporting_json, a.triage_json, + bm25(alerts_fts, 0, 10.0, 0, 3.0, 0, 2.0, 2.0, 2.0, 1.0) AS rank +FROM alerts_fts +JOIN alerts a ON a.alert_id = alerts_fts.alert_id +`+where+` +ORDER BY rank +LIMIT ?`, args...) + } else { + // No text query, just filter. + where := `WHERE 1=1` + args := []any{} + if category != "" { + where += ` AND a.category = ?` + args = append(args, category) + } + if region != "" { + where += ` AND a.region_tag = ?` + args = append(args, region) + } + if status != "" { + where += ` AND a.status = ?` + args = append(args, status) + } + args = append(args, limit) + rows, err = db.sql.QueryContext(ctx, ` +SELECT a.alert_id, a.source_id, a.status, a.first_seen, a.last_seen, a.title, + a.canonical_url, a.category, a.severity, a.region_tag, a.lat, a.lng, + a.freshness_hours, a.source_json, a.reporting_json, a.triage_json, + 0 AS rank +FROM alerts a +`+where+` +ORDER BY a.last_seen DESC +LIMIT ?`, args...) + } + if err != nil { + return nil, fmt.Errorf("search alerts: %w", err) + } + defer rows.Close() + + var results []model.Alert + for rows.Next() { + var ( + a model.Alert + sourceJSON string + reportJSON string + triageJSON string + rank float64 + ) + if err := rows.Scan(&a.AlertID, &a.SourceID, &a.Status, &a.FirstSeen, &a.LastSeen, + &a.Title, &a.CanonicalURL, &a.Category, &a.Severity, &a.RegionTag, + &a.Lat, &a.Lng, &a.FreshnessHours, &sourceJSON, &reportJSON, &triageJSON, &rank); err != nil { + return nil, fmt.Errorf("scan search result: %w", err) + } + _ = json.Unmarshal([]byte(sourceJSON), &a.Source) + _ = json.Unmarshal([]byte(reportJSON), &a.Reporting) + if triageJSON != "null" && triageJSON != "" { + var t model.Triage + if json.Unmarshal([]byte(triageJSON), &t) == nil { + a.Triage = &t + } + } + results = append(results, a) + } + return results, rows.Err() +} + func (db *DB) DeactivateSources(ctx context.Context, reasons map[string]string) error { if len(reasons) == 0 { return nil diff --git a/internal/sourcedb/schema.sql b/internal/sourcedb/schema.sql index 7ed97fc..47bc4db 100644 --- a/internal/sourcedb/schema.sql +++ b/internal/sourcedb/schema.sql @@ -159,3 +159,15 @@ CREATE VIRTUAL TABLE IF NOT EXISTS agencies_fts USING fts5( authority_type, base_url ); + +CREATE VIRTUAL TABLE IF NOT EXISTS alerts_fts USING fts5( + alert_id UNINDEXED, + title, + canonical_url UNINDEXED, + category, + severity UNINDEXED, + region_tag, + source_authority, + source_country, + source_country_code +); From d8660fc0a84fcb7ceb584cbeff6e947771d909ea Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 18:16:05 +0100 Subject: [PATCH 12/58] feat(api): add search API server with FTS5-backed /api/search Embedded HTTP server in collector process, enabled via --api flag. Supports ranked text search (BM25), category/region/status filters, auto prefix matching, and FTS5 syntax (quoted phrases, AND/OR/NOT). Caddy proxies /api/* to collector:3001 in Docker. --- docker-compose.yml | 3 + docker/Caddyfile | 4 + internal/collector/api/api.go | 133 ++++++++++++++++++++ internal/collector/api/api_test.go | 181 ++++++++++++++++++++++++++++ internal/collector/app/app.go | 18 +++ internal/collector/config/config.go | 6 + 6 files changed, 345 insertions(+) create mode 100644 internal/collector/api/api.go create mode 100644 internal/collector/api/api_test.go diff --git a/docker-compose.yml b/docker-compose.yml index e357df8..1ba93ab 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,6 +7,9 @@ services: - .env command: - --watch + - --api + - --api-addr + - ":3001" - --registry - /data/sources.db - --output diff --git a/docker/Caddyfile b/docker/Caddyfile index 5d803af..ca6cedb 100644 --- a/docker/Caddyfile +++ b/docker/Caddyfile @@ -16,6 +16,10 @@ X-Frame-Options "DENY" } + handle /api/* { + reverse_proxy collector:3001 + } + handle /alerts.json { root * /var/lib/euosint file_server diff --git a/internal/collector/api/api.go b/internal/collector/api/api.go new file mode 100644 index 0000000..d759f97 --- /dev/null +++ b/internal/collector/api/api.go @@ -0,0 +1,133 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package api + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net" + "net/http" + "strconv" + "strings" + "time" + + "github.com/scalytics/euosint/internal/sourcedb" +) + +// Server serves the search API backed by SQLite FTS5. +type Server struct { + db *sourcedb.DB + addr string + srv *http.Server + stderr io.Writer +} + +func New(db *sourcedb.DB, addr string, stderr io.Writer) *Server { + s := &Server{db: db, addr: addr, stderr: stderr} + mux := http.NewServeMux() + mux.HandleFunc("GET /api/search", s.handleSearch) + mux.HandleFunc("GET /api/health", s.handleHealth) + s.srv = &http.Server{ + Addr: addr, + Handler: cors(mux), + ReadTimeout: 5 * time.Second, + WriteTimeout: 10 * time.Second, + } + return s +} + +// Start begins listening in a goroutine. Returns once the listener is bound. +func (s *Server) Start() error { + ln, err := net.Listen("tcp", s.addr) + if err != nil { + return fmt.Errorf("api listen %s: %w", s.addr, err) + } + go func() { + if err := s.srv.Serve(ln); err != nil && err != http.ErrServerClosed { + fmt.Fprintf(s.stderr, "API server error: %v\n", err) + } + }() + return nil +} + +// Stop gracefully shuts down the server. +func (s *Server) Stop(ctx context.Context) error { + return s.srv.Shutdown(ctx) +} + +func (s *Server) handleSearch(w http.ResponseWriter, r *http.Request) { + q := strings.TrimSpace(r.URL.Query().Get("q")) + category := strings.TrimSpace(r.URL.Query().Get("category")) + region := strings.TrimSpace(r.URL.Query().Get("region")) + status := strings.TrimSpace(r.URL.Query().Get("status")) + limitStr := strings.TrimSpace(r.URL.Query().Get("limit")) + + limit := 100 + if limitStr != "" { + if n, err := strconv.Atoi(limitStr); err == nil && n > 0 && n <= 500 { + limit = n + } + } + + if q == "" && category == "" && region == "" { + writeJSON(w, http.StatusBadRequest, map[string]string{"error": "q, category, or region parameter required"}) + return + } + + // Sanitize FTS query: if user passes bare text without operators, wrap words for prefix matching. + ftsQuery := q + if q != "" && !strings.ContainsAny(q, `"*()`) && !strings.Contains(q, " OR ") && !strings.Contains(q, " AND ") && !strings.Contains(q, " NOT ") { + words := strings.Fields(q) + parts := make([]string, len(words)) + for i, w := range words { + parts[i] = `"` + strings.ReplaceAll(w, `"`, `""`) + `"` + "*" + } + ftsQuery = strings.Join(parts, " ") + } + + results, err := s.db.SearchAlerts(r.Context(), ftsQuery, category, region, status, limit) + if err != nil { + // FTS parse error — try as plain phrase. + if strings.Contains(err.Error(), "fts5") || strings.Contains(err.Error(), "syntax") { + phrase := `"` + strings.ReplaceAll(q, `"`, `""`) + `"` + results, err = s.db.SearchAlerts(r.Context(), phrase, category, region, status, limit) + } + if err != nil { + writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) + return + } + } + writeJSON(w, http.StatusOK, map[string]any{ + "query": q, + "count": len(results), + "results": results, + }) +} + +func (s *Server) handleHealth(w http.ResponseWriter, _ *http.Request) { + writeJSON(w, http.StatusOK, map[string]string{"status": "ok"}) +} + +func writeJSON(w http.ResponseWriter, status int, v any) { + w.Header().Set("Content-Type", "application/json; charset=utf-8") + w.WriteHeader(status) + enc := json.NewEncoder(w) + enc.SetEscapeHTML(false) + _ = enc.Encode(v) +} + +func cors(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type") + if r.Method == http.MethodOptions { + w.WriteHeader(http.StatusNoContent) + return + } + next.ServeHTTP(w, r) + }) +} diff --git a/internal/collector/api/api_test.go b/internal/collector/api/api_test.go new file mode 100644 index 0000000..d4a6127 --- /dev/null +++ b/internal/collector/api/api_test.go @@ -0,0 +1,181 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package api + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "os" + "path/filepath" + "testing" + + "github.com/scalytics/euosint/internal/collector/model" + "github.com/scalytics/euosint/internal/sourcedb" +) + +func testDB(t *testing.T) *sourcedb.DB { + t.Helper() + dir := t.TempDir() + db, err := sourcedb.Open(filepath.Join(dir, "test.db")) + if err != nil { + t.Fatal(err) + } + if err := db.Init(context.Background()); err != nil { + t.Fatal(err) + } + return db +} + +func seedAlerts(t *testing.T, db *sourcedb.DB) { + t.Helper() + alerts := []model.Alert{ + { + AlertID: "a1", + SourceID: "europol", + Status: "active", + Title: "Europol dismantles major drug trafficking network", + CanonicalURL: "https://europol.europa.eu/a1", + Category: "public_appeal", + Severity: "high", + RegionTag: "EU", + Source: model.SourceMetadata{ + SourceID: "europol", + AuthorityName: "Europol", + Country: "Netherlands", + CountryCode: "NL", + Region: "Europe", + }, + }, + { + AlertID: "a2", + SourceID: "fbi-wanted", + Status: "active", + Title: "FBI Most Wanted: Cyber fugitive identified", + CanonicalURL: "https://fbi.gov/a2", + Category: "wanted_suspect", + Severity: "critical", + RegionTag: "US", + Source: model.SourceMetadata{ + SourceID: "fbi-wanted", + AuthorityName: "FBI", + Country: "United States", + CountryCode: "US", + Region: "North America", + }, + }, + { + AlertID: "a3", + SourceID: "cert-ua", + Status: "active", + Title: "CERT-UA reports new malware campaign targeting energy sector", + CanonicalURL: "https://cert.gov.ua/a3", + Category: "cyber_advisory", + Severity: "high", + RegionTag: "UA", + Source: model.SourceMetadata{ + SourceID: "cert-ua", + AuthorityName: "CERT-UA", + Country: "Ukraine", + CountryCode: "UA", + Region: "Europe", + }, + }, + } + if err := db.SaveAlerts(context.Background(), alerts); err != nil { + t.Fatal(err) + } +} + +func TestSearchReturnsRankedResults(t *testing.T) { + db := testDB(t) + defer db.Close() + seedAlerts(t, db) + + srv := New(db, ":0", os.Stderr) + handler := srv.srv.Handler + + req := httptest.NewRequest("GET", "/api/search?q=drug+trafficking", nil) + w := httptest.NewRecorder() + handler.ServeHTTP(w, req) + + if w.Code != http.StatusOK { + t.Fatalf("expected 200, got %d: %s", w.Code, w.Body.String()) + } + var resp struct { + Count int `json:"count"` + Results []model.Alert `json:"results"` + } + if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { + t.Fatal(err) + } + if resp.Count == 0 { + t.Fatal("expected search results for 'drug trafficking'") + } + if resp.Results[0].AlertID != "a1" { + t.Fatalf("expected Europol alert first, got %s", resp.Results[0].AlertID) + } +} + +func TestSearchWithCategoryFilter(t *testing.T) { + db := testDB(t) + defer db.Close() + seedAlerts(t, db) + + srv := New(db, ":0", os.Stderr) + handler := srv.srv.Handler + + req := httptest.NewRequest("GET", "/api/search?category=cyber_advisory", nil) + w := httptest.NewRecorder() + handler.ServeHTTP(w, req) + + if w.Code != http.StatusOK { + t.Fatalf("expected 200, got %d: %s", w.Code, w.Body.String()) + } + var resp struct { + Count int `json:"count"` + Results []model.Alert `json:"results"` + } + if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { + t.Fatal(err) + } + for _, r := range resp.Results { + if r.Category != "cyber_advisory" { + t.Fatalf("expected only cyber_advisory, got %s", r.Category) + } + } +} + +func TestSearchEmptyQueryReturns400(t *testing.T) { + db := testDB(t) + defer db.Close() + + srv := New(db, ":0", os.Stderr) + handler := srv.srv.Handler + + req := httptest.NewRequest("GET", "/api/search", nil) + w := httptest.NewRecorder() + handler.ServeHTTP(w, req) + + if w.Code != http.StatusBadRequest { + t.Fatalf("expected 400, got %d", w.Code) + } +} + +func TestHealthEndpoint(t *testing.T) { + db := testDB(t) + defer db.Close() + + srv := New(db, ":0", os.Stderr) + handler := srv.srv.Handler + + req := httptest.NewRequest("GET", "/api/health", nil) + w := httptest.NewRecorder() + handler.ServeHTTP(w, req) + + if w.Code != http.StatusOK { + t.Fatalf("expected 200, got %d", w.Code) + } +} diff --git a/internal/collector/app/app.go b/internal/collector/app/app.go index 038f7ea..352a3f0 100644 --- a/internal/collector/app/app.go +++ b/internal/collector/app/app.go @@ -9,6 +9,7 @@ import ( "fmt" "io" + "github.com/scalytics/euosint/internal/collector/api" "github.com/scalytics/euosint/internal/collector/config" "github.com/scalytics/euosint/internal/collector/discover" "github.com/scalytics/euosint/internal/collector/run" @@ -64,6 +65,8 @@ func Run(ctx context.Context, args []string, stdout io.Writer, stderr io.Writer) fs.BoolVar(&cfg.SourceDBMergeRegistry, "source-db-merge-registry", cfg.SourceDBMergeRegistry, "Merge a JSON registry or curated seed into the SQLite source database") fs.BoolVar(&cfg.SourceDBExportRegistry, "source-db-export-registry", cfg.SourceDBExportRegistry, "Export the SQLite source database back into the JSON registry") fs.StringVar(&cfg.CuratedSeedPath, "curated-seed", cfg.CuratedSeedPath, "Path to the curated agency seed JSON file") + fs.BoolVar(&cfg.APIEnabled, "api", cfg.APIEnabled, "Start the search API server alongside the collector") + fs.StringVar(&cfg.APIAddr, "api-addr", cfg.APIAddr, "Listen address for the search API server") if err := fs.Parse(args); err != nil { return err @@ -112,5 +115,20 @@ func Run(ctx context.Context, args []string, stdout io.Writer, stderr io.Writer) return nil } + if cfg.APIEnabled { + apiDB, err := sourcedb.Open(cfg.RegistryPath) + if err != nil { + return fmt.Errorf("open DB for API: %w", err) + } + defer apiDB.Close() + + srv := api.New(apiDB, cfg.APIAddr, stderr) + if err := srv.Start(); err != nil { + return err + } + defer srv.Stop(ctx) + fmt.Fprintf(stdout, "Search API listening on %s\n", cfg.APIAddr) + } + return run.New(stdout, stderr).Run(ctx, cfg) } diff --git a/internal/collector/config/config.go b/internal/collector/config/config.go index 8d0fcd0..7243dca 100644 --- a/internal/collector/config/config.go +++ b/internal/collector/config/config.go @@ -73,6 +73,8 @@ type Config struct { SourceDBMergeRegistry bool SourceDBExportRegistry bool CuratedSeedPath string + APIEnabled bool + APIAddr string } func Default() Config { @@ -125,6 +127,8 @@ func Default() Config { SourceDBMergeRegistry: false, SourceDBExportRegistry: false, CuratedSeedPath: "registry/curated_agencies.seed.json", + APIEnabled: false, + APIAddr: ":3001", } } @@ -179,6 +183,8 @@ func FromEnv() Config { cfg.SourceDBMergeRegistry = envBool("SOURCE_DB_MERGE_REGISTRY", cfg.SourceDBMergeRegistry) cfg.SourceDBExportRegistry = envBool("SOURCE_DB_EXPORT_REGISTRY", cfg.SourceDBExportRegistry) cfg.CuratedSeedPath = envString("CURATED_SEED_PATH", cfg.CuratedSeedPath) + cfg.APIEnabled = envBool("API_ENABLED", cfg.APIEnabled) + cfg.APIAddr = envString("API_ADDR", cfg.APIAddr) return cfg } From 2a393ba019e94d637ef7a2153b15d6e1de9ce588 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 18:16:13 +0100 Subject: [PATCH 13/58] feat(ui): wire search bar to FTS5 API with client-side fallback useSearch hook probes /api/health on mount, then sends debounced queries to /api/search. When API is unavailable, falls back to the existing in-memory string.includes() filter. --- src/App.tsx | 18 +++++++-- src/hooks/useSearch.ts | 88 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 src/hooks/useSearch.ts diff --git a/src/App.tsx b/src/App.tsx index 199d1b6..491a581 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -11,6 +11,7 @@ import { AlertFeed } from "@/components/AlertFeed"; import { AlertDetail } from "@/components/AlertDetail"; import { FeedDirectory } from "@/components/FeedDirectory"; import { useAlerts } from "@/hooks/useAlerts"; +import { useSearch } from "@/hooks/useSearch"; import { useSourceHealth } from "@/hooks/useSourceHealth"; import { alertMatchesRegionFilter } from "@/lib/regions"; import type { AlertCategory } from "@/types/alert"; @@ -48,7 +49,7 @@ export default function App() { const [selectedSourceIds, setSelectedSourceIds] = useState([]); const [categoryFilter, setCategoryFilter] = useState("all"); const [regionFilter, setRegionFilter] = useState("Europe"); - const [searchQuery, setSearchQuery] = useState(""); + const { query: searchQuery, setQuery: setSearchQuery, results: searchResults, isApiAvailable } = useSearch(); const [visibleAlertIds, setVisibleAlertIds] = useState([]); const [mobilePane, setMobilePane] = useState<"intel" | "map" | "alerts">("map"); const panelRef = useRef(null); @@ -79,11 +80,22 @@ export default function App() { }, []); const regionScopedAlerts = useMemo(() => { + const query = searchQuery.trim().toLowerCase(); + + // When API search returned results, use those (already ranked by BM25). + if (query && isApiAvailable && searchResults.length > 0) { + let filtered = searchResults; + if (regionFilter !== "all") { + filtered = filtered.filter((alert) => alertMatchesRegionFilter(alert, regionFilter)); + } + return filtered; + } + + // Fallback: client-side filter. let filtered = alerts; if (regionFilter !== "all") { filtered = filtered.filter((alert) => alertMatchesRegionFilter(alert, regionFilter)); } - const query = searchQuery.trim().toLowerCase(); if (query) { filtered = filtered.filter((alert) => { const haystack = [ @@ -101,7 +113,7 @@ export default function App() { }); } return filtered; - }, [alerts, regionFilter, searchQuery]); + }, [alerts, regionFilter, searchQuery, searchResults, isApiAvailable]); const scopedAlerts = useMemo(() => { let filtered = regionScopedAlerts; diff --git a/src/hooks/useSearch.ts b/src/hooks/useSearch.ts new file mode 100644 index 0000000..02e5533 --- /dev/null +++ b/src/hooks/useSearch.ts @@ -0,0 +1,88 @@ +/* + * EUOSINT + * Portions derived from novatechflow/osint-siem and cyberdude88/osint-siem. + * See NOTICE for provenance and LICENSE for repository-local terms. + */ + +import { useCallback, useEffect, useRef, useState } from "react"; +import type { Alert } from "@/types/alert"; + +const SEARCH_URL = `${import.meta.env.BASE_URL}api/search`; +const DEBOUNCE_MS = 300; + +interface SearchResult { + query: string; + count: number; + results: Alert[]; +} + +export function useSearch() { + const [query, setQuery] = useState(""); + const [results, setResults] = useState([]); + const [isSearching, setIsSearching] = useState(false); + const [isApiAvailable, setIsApiAvailable] = useState(null); + const abortRef = useRef(null); + const timerRef = useRef | null>(null); + + // Probe API availability once on mount. + useEffect(() => { + fetch(`${SEARCH_URL.replace("/search", "/health")}`, { cache: "no-store" }) + .then((r) => setIsApiAvailable(r.ok)) + .catch(() => setIsApiAvailable(false)); + }, []); + + const search = useCallback( + async (q: string) => { + abortRef.current?.abort(); + + const trimmed = q.trim(); + if (!trimmed || !isApiAvailable) { + setResults([]); + setIsSearching(false); + return; + } + + const controller = new AbortController(); + abortRef.current = controller; + setIsSearching(true); + + try { + const url = `${SEARCH_URL}?q=${encodeURIComponent(trimmed)}&limit=200`; + const response = await fetch(url, { + signal: controller.signal, + cache: "no-store", + }); + if (!response.ok) throw new Error(`${response.status}`); + const data = (await response.json()) as SearchResult; + if (!controller.signal.aborted) { + setResults(data.results ?? []); + } + } catch { + if (!controller.signal.aborted) { + setResults([]); + } + } finally { + if (!controller.signal.aborted) { + setIsSearching(false); + } + } + }, + [isApiAvailable], + ); + + // Debounced search trigger. + useEffect(() => { + if (timerRef.current) clearTimeout(timerRef.current); + if (!query.trim()) { + setResults([]); + setIsSearching(false); + return; + } + timerRef.current = setTimeout(() => search(query), DEBOUNCE_MS); + return () => { + if (timerRef.current) clearTimeout(timerRef.current); + }; + }, [query, search]); + + return { query, setQuery, results, isSearching, isApiAvailable }; +} From b76c46bd68d8571bfde12bd1fae69ce2e6032b36 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 18:16:20 +0100 Subject: [PATCH 14/58] fix(interpol): add XHR headers to bypass Akamai WAF Interpol API requires Referer, Origin, and Sec-Fetch-* headers mimicking an XHR from www.interpol.int. Without these, Akamai returns 403. Verified: 6,455 Red + 11,271 Yellow notices accessible. --- internal/collector/run/run.go | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/internal/collector/run/run.go b/internal/collector/run/run.go index e9bef2d..3e2adab 100644 --- a/internal/collector/run/run.go +++ b/internal/collector/run/run.go @@ -312,9 +312,29 @@ func (r Runner) fetchInterpol(ctx context.Context, fetcher fetch.Fetcher, browse pageSize := 20 var allNotices []model.Alert + // Interpol's API sits behind Akamai WAF and requires XHR-style headers + // with Referer/Origin pointing to the Interpol website. + interpolHeaders := map[string]string{ + "Referer": "https://www.interpol.int/How-we-work/Notices/View-Notices", + "Origin": "https://www.interpol.int", + "Sec-Fetch-Dest": "empty", + "Sec-Fetch-Mode": "cors", + "Sec-Fetch-Site": "same-site", + "X-Requested-With": "XMLHttpRequest", + } + + // Use TextWithHeaders if the fetcher is a *Client (stealth HTTP). + clientFetcher, isClient := fetcher.(*fetch.Client) + for page := 1; len(allNotices) < limit; page++ { pageURL := buildInterpolPageURL(source.FeedURL, page, pageSize) - body, err := fetcher.Text(ctx, pageURL, source.FollowRedirects, "application/json") + var body []byte + var err error + if isClient { + body, err = clientFetcher.TextWithHeaders(ctx, pageURL, source.FollowRedirects, "application/json", interpolHeaders) + } else { + body, err = fetcher.Text(ctx, pageURL, source.FollowRedirects, "application/json") + } if err != nil { // If first page fails, try browser fallback for the whole batch. if page == 1 && browser != nil { From 9150d26c8f4e1707950631fc812c286f081c473b Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 18:33:47 +0100 Subject: [PATCH 15/58] feat(collector): add FBI Wanted API source type and browser mode for US agencies - New fbi-wanted-json source type hitting api.fbi.gov public API - Parser extracts name, charges, nationality, aliases, reward, armed-dangerous - 4 FBI subcategories: wanted, ten-most-wanted, seeking-info, parental-kidnappings - Add fetch_mode: browser to DEA and ATF (blocked by stealth HTTP) - New dea-fugitives and usms-mostwanted browser-backed sources - Remove duplicate fbi-seeking and fbi-mostwanted registry entries --- internal/collector/model/source.go | 2 +- internal/collector/normalize/normalize.go | 16 ++ internal/collector/parse/fbi.go | 126 +++++++++++++++ internal/collector/parse/fbi_test.go | 88 +++++++++++ internal/collector/run/run.go | 52 +++++++ registry/source_registry.json | 182 ++++++++++++++-------- 6 files changed, 404 insertions(+), 62 deletions(-) create mode 100644 internal/collector/parse/fbi.go create mode 100644 internal/collector/parse/fbi_test.go diff --git a/internal/collector/model/source.go b/internal/collector/model/source.go index 1abb519..d1ee7bd 100644 --- a/internal/collector/model/source.go +++ b/internal/collector/model/source.go @@ -4,7 +4,7 @@ package model // Supported source types: rss, html-list, kev-json, interpol-red-json, -// interpol-yellow-json, travelwarning-json, travelwarning-atom. +// interpol-yellow-json, fbi-wanted-json, travelwarning-json, travelwarning-atom. type RegistrySource struct { Type string `json:"type"` FetchMode string `json:"fetch_mode,omitempty"` // "stealth" (default) or "browser" diff --git a/internal/collector/normalize/normalize.go b/internal/collector/normalize/normalize.go index 0661db8..b344994 100644 --- a/internal/collector/normalize/normalize.go +++ b/internal/collector/normalize/normalize.go @@ -228,6 +228,22 @@ func InterpolAlert(ctx Context, meta model.RegistrySource, noticeID string, titl return &alert } +func FBIWantedAlert(ctx Context, meta model.RegistrySource, item parse.FeedItem) *model.Alert { + publishedAt := parseDate(item.Published) + if publishedAt.IsZero() { + publishedAt = ctx.Now + } + alert := baseAlert(ctx, meta, item.Title, item.Link, publishedAt) + alert.Severity = "critical" + triage := score(ctx.Config, alert, FeedContext{ + Summary: item.Summary, + Tags: item.Tags, + FeedType: meta.Type, + }) + alert.Triage = triage + return &alert +} + func TravelWarningAlert(ctx Context, meta model.RegistrySource, item parse.FeedItem) *model.Alert { publishedAt := parseDate(item.Published) if publishedAt.IsZero() { diff --git a/internal/collector/parse/fbi.go b/internal/collector/parse/fbi.go new file mode 100644 index 0000000..3d9e0b9 --- /dev/null +++ b/internal/collector/parse/fbi.go @@ -0,0 +1,126 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package parse + +import ( + "encoding/json" + "strings" +) + +// FBIWantedResponse is the top-level response from the FBI Wanted API. +type FBIWantedResponse struct { + Total int `json:"total"` + Page int `json:"page"` + Items []FBIWantedEntry `json:"items"` +} + +// FBIWantedEntry is a single person/case from the FBI Wanted API. +type FBIWantedEntry struct { + UID string `json:"uid"` + Title string `json:"title"` + Description string `json:"description"` + Details string `json:"details"` + Caution string `json:"caution"` + WarningMessage string `json:"warning_message"` + Remarks string `json:"remarks"` + Sex string `json:"sex"` + Nationality string `json:"nationality"` + PlaceOfBirth string `json:"place_of_birth"` + DatesOfBirthUsed []string `json:"dates_of_birth_used"` + Aliases []string `json:"aliases"` + Subjects []string `json:"subjects"` + Status string `json:"status"` + PersonClassification string `json:"person_classification"` + PosterClassification string `json:"poster_classification"` + RewardText string `json:"reward_text"` + RewardMin int `json:"reward_min"` + RewardMax int `json:"reward_max"` + URL string `json:"url"` + Path string `json:"path"` + Publication string `json:"publication"` + Modified string `json:"modified"` + FieldOffices []string `json:"field_offices"` + PossibleCountries []string `json:"possible_countries"` + PossibleStates []string `json:"possible_states"` + Images []struct { + Thumb string `json:"thumb"` + Original string `json:"original"` + Large string `json:"large"` + Caption string `json:"caption"` + } `json:"images"` +} + +// ParseFBIWanted parses the FBI Wanted API JSON response into FeedItems. +func ParseFBIWanted(body []byte) ([]FeedItem, int, error) { + var resp FBIWantedResponse + if err := json.Unmarshal(body, &resp); err != nil { + return nil, 0, err + } + items := make([]FeedItem, 0, len(resp.Items)) + for _, entry := range resp.Items { + title := strings.TrimSpace(entry.Title) + if title == "" { + continue + } + link := strings.TrimSpace(entry.URL) + if link == "" && strings.TrimSpace(entry.Path) != "" { + link = "https://www.fbi.gov" + entry.Path + } + if link == "" { + link = "https://www.fbi.gov/wanted" + } + + summary := buildFBISummary(entry) + tags := buildFBITags(entry) + published := firstNonEmpty(entry.Modified, entry.Publication) + + items = append(items, FeedItem{ + Title: title, + Link: link, + Published: published, + Summary: summary, + Tags: tags, + }) + } + return items, resp.Total, nil +} + +func buildFBISummary(entry FBIWantedEntry) string { + parts := []string{} + if desc := stripHTML(entry.Description); desc != "" { + parts = append(parts, desc) + } + if entry.Nationality != "" { + parts = append(parts, "Nationality: "+entry.Nationality) + } + if entry.PlaceOfBirth != "" { + parts = append(parts, "Born: "+entry.PlaceOfBirth) + } + if len(entry.Aliases) > 0 { + parts = append(parts, "Aliases: "+strings.Join(entry.Aliases, ", ")) + } + if entry.RewardText != "" { + parts = append(parts, "Reward: "+stripHTML(entry.RewardText)) + } + return strings.Join(parts, ". ") +} + +func buildFBITags(entry FBIWantedEntry) []string { + tags := make([]string, 0, len(entry.Subjects)+4) + tags = append(tags, entry.Subjects...) + if entry.PosterClassification != "" { + tags = append(tags, entry.PosterClassification) + } + if entry.PersonClassification != "" { + tags = append(tags, entry.PersonClassification) + } + if entry.Sex != "" { + tags = append(tags, entry.Sex) + } + if entry.WarningMessage != "" { + tags = append(tags, "armed-dangerous") + } + return tags +} + diff --git a/internal/collector/parse/fbi_test.go b/internal/collector/parse/fbi_test.go new file mode 100644 index 0000000..f3b4f40 --- /dev/null +++ b/internal/collector/parse/fbi_test.go @@ -0,0 +1,88 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package parse + +import "testing" + +func TestParseFBIWanted(t *testing.T) { + body := []byte(`{ + "total": 1137, + "page": 1, + "items": [ + { + "uid": "abc123", + "title": "JOHN DOE", + "description": "

Conspiracy to commit wire fraud

", + "url": "https://www.fbi.gov/wanted/fugitive/john-doe", + "nationality": "American", + "place_of_birth": "New York, New York", + "aliases": ["JD", "Johnny"], + "subjects": ["Cyber's Most Wanted"], + "person_classification": "Main", + "poster_classification": "default", + "sex": "Male", + "warning_message": "SHOULD BE CONSIDERED ARMED AND DANGEROUS", + "reward_text": "Up to $100,000", + "publication": "2025-01-15T00:00:00", + "modified": "2026-03-01T12:00:00", + "images": [{"thumb": "https://www.fbi.gov/image/thumb.jpg"}] + }, + { + "uid": "def456", + "title": "", + "url": "" + } + ] + }`) + + items, total, err := ParseFBIWanted(body) + if err != nil { + t.Fatal(err) + } + if total != 1137 { + t.Fatalf("expected total 1137, got %d", total) + } + if len(items) != 1 { + t.Fatalf("expected 1 item (empty title skipped), got %d", len(items)) + } + + item := items[0] + if item.Title != "JOHN DOE" { + t.Fatalf("expected title 'JOHN DOE', got %q", item.Title) + } + if item.Link != "https://www.fbi.gov/wanted/fugitive/john-doe" { + t.Fatalf("expected FBI link, got %q", item.Link) + } + if item.Published != "2026-03-01T12:00:00" { + t.Fatalf("expected modified date, got %q", item.Published) + } + // Summary should contain stripped HTML description. + if item.Summary == "" { + t.Fatal("expected non-empty summary") + } + // Tags should include subjects, classification, sex, armed-dangerous. + foundArmed := false + for _, tag := range item.Tags { + if tag == "armed-dangerous" { + foundArmed = true + } + } + if !foundArmed { + t.Fatalf("expected armed-dangerous tag, got %v", item.Tags) + } +} + +func TestParseFBIWantedEmpty(t *testing.T) { + body := []byte(`{"total": 0, "page": 1, "items": []}`) + items, total, err := ParseFBIWanted(body) + if err != nil { + t.Fatal(err) + } + if total != 0 { + t.Fatalf("expected total 0, got %d", total) + } + if len(items) != 0 { + t.Fatalf("expected 0 items, got %d", len(items)) + } +} diff --git a/internal/collector/run/run.go b/internal/collector/run/run.go index 3e2adab..9ba2fed 100644 --- a/internal/collector/run/run.go +++ b/internal/collector/run/run.go @@ -178,6 +178,8 @@ func (r Runner) fetchSource(ctx context.Context, fetcher fetch.Fetcher, browser return r.fetchKEV(ctx, fetcher, nctx, source) case "interpol-red-json", "interpol-yellow-json": return r.fetchInterpol(ctx, fetcher, browser, nctx, source) + case "fbi-wanted-json": + return r.fetchFBIWanted(ctx, fetcher, nctx, source) case "travelwarning-json": return r.fetchTravelWarningJSON(ctx, fetcher, nctx, source) case "travelwarning-atom": @@ -483,6 +485,56 @@ func extractInterpolNoticeID(entityID string, link string) string { return strings.TrimSpace(parts[len(parts)-1]) } +func (r Runner) fetchFBIWanted(ctx context.Context, fetcher fetch.Fetcher, nctx normalize.Context, source model.RegistrySource) ([]model.Alert, error) { + limit := perSourceLimit(nctx.Config, source) + pageSize := 40 + var allAlerts []model.Alert + + for page := 1; len(allAlerts) < limit; page++ { + pageURL := fmt.Sprintf("%s&page=%d&pageSize=%d", source.FeedURL, page, pageSize) + body, err := fetcher.Text(ctx, pageURL, source.FollowRedirects, "application/json") + if err != nil { + if page == 1 { + return nil, err + } + break + } + items, total, err := parse.ParseFBIWanted(body) + if err != nil { + if page == 1 { + return nil, err + } + break + } + for _, item := range items { + if len(allAlerts) >= limit { + break + } + if strings.TrimSpace(item.Title) == "" { + continue + } + alert := normalize.FBIWantedAlert(nctx, source, item) + if alert != nil { + allAlerts = append(allAlerts, *alert) + } + } + // Stop if we've fetched all available or last page was partial. + if total > 0 && page*pageSize >= total { + break + } + if len(items) < pageSize { + break + } + // Polite delay between pages. + select { + case <-time.After(1 * time.Second): + case <-ctx.Done(): + return allAlerts, nil + } + } + return allAlerts, nil +} + func (r Runner) fetchTravelWarningJSON(ctx context.Context, fetcher fetch.Fetcher, nctx normalize.Context, source model.RegistrySource) ([]model.Alert, error) { body, err := fetcher.Text(ctx, source.FeedURL, source.FollowRedirects, "application/json") if err != nil { diff --git a/registry/source_registry.json b/registry/source_registry.json index 2167396..8de5be3 100644 --- a/registry/source_registry.json +++ b/registry/source_registry.json @@ -23,49 +23,99 @@ "max_items": 15 }, { - "type": "rss", + "type": "fbi-wanted-json", "source": { - "source_id": "fbi", - "authority_name": "FBI", + "source_id": "fbi-wanted", + "authority_name": "FBI Wanted", "country": "United States", "country_code": "US", "region": "North America", "authority_type": "police", "base_url": "https://www.fbi.gov" }, - "feed_url": "https://www.fbi.gov/wanted/seeking-information", - "category": "public_appeal", + "feed_url": "https://api.fbi.gov/wanted/v1/list?posterClassification=default", + "category": "wanted_suspect", "region_tag": "US", "lat": 38.9, "lng": -77, + "max_items": 100, "reporting": { - "label": "Report to FBI", + "label": "Submit a Tip to FBI", "url": "https://tips.fbi.gov/", "phone": "1-800-CALL-FBI (1-800-225-5324)", "notes": "Use 911 for emergencies." } }, { - "type": "rss", + "type": "fbi-wanted-json", "source": { - "source_id": "fbi-wanted", - "authority_name": "FBI Wanted", + "source_id": "fbi-mostwanted", + "authority_name": "FBI Ten Most Wanted", "country": "United States", "country_code": "US", "region": "North America", "authority_type": "police", "base_url": "https://www.fbi.gov" }, - "feed_url": "https://www.fbi.gov/wanted", + "feed_url": "https://api.fbi.gov/wanted/v1/list?posterClassification=ten", "category": "wanted_suspect", "region_tag": "US", - "lat": 38.9, - "lng": -77, + "lat": 38.89, + "lng": -77.02, + "max_items": 20, + "reporting": { + "label": "Report Sighting to FBI", + "url": "https://tips.fbi.gov/", + "phone": "1-800-CALL-FBI (1-800-225-5324)", + "notes": "Do NOT attempt to apprehend. Call 911 immediately if in danger." + } + }, + { + "type": "fbi-wanted-json", + "source": { + "source_id": "fbi-seeking", + "authority_name": "FBI Seeking Info", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "police", + "base_url": "https://www.fbi.gov" + }, + "feed_url": "https://api.fbi.gov/wanted/v1/list?posterClassification=seeking-info", + "category": "public_appeal", + "region_tag": "US", + "lat": 38.91, + "lng": -77.01, + "max_items": 60, "reporting": { "label": "Submit a Tip to FBI", "url": "https://tips.fbi.gov/", "phone": "1-800-CALL-FBI (1-800-225-5324)", - "notes": "Use 911 for emergencies." + "notes": "The FBI is seeking the public's assistance. If you have information, submit a tip." + } + }, + { + "type": "fbi-wanted-json", + "source": { + "source_id": "fbi-kidnappings", + "authority_name": "FBI Parental Kidnappings", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "police", + "base_url": "https://www.fbi.gov" + }, + "feed_url": "https://api.fbi.gov/wanted/v1/list?posterClassification=kidnappings", + "category": "missing_person", + "region_tag": "US", + "lat": 38.88, + "lng": -76.99, + "max_items": 40, + "reporting": { + "label": "Report to FBI", + "url": "https://tips.fbi.gov/", + "phone": "1-800-CALL-FBI (1-800-225-5324)", + "notes": "If you have information about a parental kidnapping case, submit a tip." } }, { @@ -432,6 +482,7 @@ }, { "type": "html-list", + "fetch_mode": "browser", "followRedirects": true, "source": { "source_id": "dea", @@ -471,6 +522,7 @@ }, { "type": "html-list", + "fetch_mode": "browser", "followRedirects": true, "source": { "source_id": "atf", @@ -508,6 +560,62 @@ "subscribe for atf updates" ] }, + { + "type": "html-list", + "fetch_mode": "browser", + "followRedirects": true, + "source": { + "source_id": "dea-fugitives", + "authority_name": "DEA Fugitives", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "police", + "base_url": "https://www.dea.gov" + }, + "feed_url": "https://www.dea.gov/fugitives", + "category": "wanted_suspect", + "region_tag": "US", + "lat": 38.87, + "lng": -77.06, + "max_items": 60, + "reporting": { + "label": "Report to DEA", + "url": "https://www.dea.gov/submit-tip", + "phone": "1-877-792-2873" + }, + "include_keywords": [ + "wanted", + "fugitive", + "reward" + ] + }, + { + "type": "html-list", + "fetch_mode": "browser", + "followRedirects": true, + "source": { + "source_id": "usms-mostwanted", + "authority_name": "US Marshals Most Wanted", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "police", + "base_url": "https://www.usmarshals.gov" + }, + "feed_url": "https://www.usmarshals.gov/what-we-do/fugitive-investigations/15-most-wanted", + "category": "wanted_suspect", + "region_tag": "US", + "lat": 38.9, + "lng": -77.03, + "max_items": 20, + "reporting": { + "label": "Report to US Marshals", + "url": "https://www.usmarshals.gov/tips", + "phone": "1-877-926-8332", + "notes": "Do NOT attempt to apprehend. Call 911 immediately if in danger." + } + }, { "type": "rss", "followRedirects": true, @@ -1173,54 +1281,6 @@ "notes": "Coordinate with local police for urgent leads." } }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "fbi-seeking", - "authority_name": "FBI Seeking Info", - "country": "United States", - "country_code": "US", - "region": "North America", - "authority_type": "police", - "base_url": "https://www.fbi.gov" - }, - "feed_url": "https://www.fbi.gov/wanted/seeking-information", - "category": "public_appeal", - "region_tag": "US", - "lat": 38.91, - "lng": -77.01, - "reporting": { - "label": "Submit a Tip to FBI", - "url": "https://tips.fbi.gov/", - "phone": "1-800-CALL-FBI (1-800-225-5324)", - "notes": "The FBI is seeking the public's assistance. If you have information, submit a tip." - } - }, - { - "type": "rss", - "followRedirects": true, - "source": { - "source_id": "fbi-mostwanted", - "authority_name": "FBI Most Wanted", - "country": "United States", - "country_code": "US", - "region": "North America", - "authority_type": "police", - "base_url": "https://www.fbi.gov" - }, - "feed_url": "https://www.fbi.gov/wanted", - "category": "wanted_suspect", - "region_tag": "US", - "lat": 38.89, - "lng": -77.02, - "reporting": { - "label": "Report Sighting to FBI", - "url": "https://tips.fbi.gov/", - "phone": "1-800-CALL-FBI (1-800-225-5324)", - "notes": "Do NOT attempt to apprehend. Call 911 immediately if in danger." - } - }, { "type": "rss", "followRedirects": true, From 8029b46aa063ab6cfac8cac59c8974657a1d76db Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 18:41:08 +0100 Subject: [PATCH 16/58] feat(api): add per-IP token bucket rate limiter on search endpoint - 30-request burst, 5/sec refill, stale eviction after 10min - Returns 429 with Retry-After header when exceeded - Health endpoint exempt from rate limiting - Extracts client IP from X-Forwarded-For/X-Real-Ip - Makefile dev-stop/dev-restart now prune dangling images and build cache --- Makefile | 8 ++- internal/collector/api/api.go | 98 +++++++++++++++++++++++++++++- internal/collector/api/api_test.go | 53 ++++++++++++++++ 3 files changed, 156 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index c7c6b7d..a61f9c4 100644 --- a/Makefile +++ b/Makefile @@ -127,11 +127,15 @@ dev-start: ## Start the local HTTP dev stack on localhost @echo "EUOSINT available at http://localhost:$${EUOSINT_HTTP_PORT:-8080}" @open "http://localhost:$${EUOSINT_HTTP_PORT:-8080}" -dev-stop: ## Stop the local dev stack +dev-stop: ## Stop the local dev stack and prune dangling images $(DOCKER_COMPOSE) down --remove-orphans + @docker image prune -f --filter "label=com.docker.compose.project" >/dev/null 2>&1 || true + @docker builder prune -f >/dev/null 2>&1 || true -dev-restart: ## Restart the local dev stack +dev-restart: ## Restart the local dev stack (prunes old images first) $(DOCKER_COMPOSE) down --remove-orphans + @docker image prune -f --filter "label=com.docker.compose.project" >/dev/null 2>&1 || true + @docker builder prune -f >/dev/null 2>&1 || true $(DOCKER_COMPOSE) up --build -d @echo "EUOSINT available at http://localhost:$${EUOSINT_HTTP_PORT:-8080}" @open "http://localhost:$${EUOSINT_HTTP_PORT:-8080}" diff --git a/internal/collector/api/api.go b/internal/collector/api/api.go index d759f97..33a15e9 100644 --- a/internal/collector/api/api.go +++ b/internal/collector/api/api.go @@ -12,6 +12,7 @@ import ( "net/http" "strconv" "strings" + "sync" "time" "github.com/scalytics/euosint/internal/sourcedb" @@ -30,9 +31,10 @@ func New(db *sourcedb.DB, addr string, stderr io.Writer) *Server { mux := http.NewServeMux() mux.HandleFunc("GET /api/search", s.handleSearch) mux.HandleFunc("GET /api/health", s.handleHealth) + rl := newRateLimiter(30, 5, 10*time.Minute) // 30 requests burst, 5/sec refill s.srv = &http.Server{ Addr: addr, - Handler: cors(mux), + Handler: cors(rateLimit(rl, mux)), ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, } @@ -131,3 +133,97 @@ func cors(next http.Handler) http.Handler { next.ServeHTTP(w, r) }) } + +// ---------- per-IP token bucket rate limiter ---------- + +type ipBucket struct { + tokens float64 + lastSeen time.Time +} + +type rateLimiterState struct { + mu sync.Mutex + buckets map[string]*ipBucket + burst float64 + rate float64 // tokens per second + staleAge time.Duration +} + +func newRateLimiter(burst int, perSecond float64, staleAge time.Duration) *rateLimiterState { + rl := &rateLimiterState{ + buckets: make(map[string]*ipBucket), + burst: float64(burst), + rate: perSecond, + staleAge: staleAge, + } + go rl.evictLoop() + return rl +} + +func (rl *rateLimiterState) allow(ip string) bool { + rl.mu.Lock() + defer rl.mu.Unlock() + now := time.Now() + b, ok := rl.buckets[ip] + if !ok { + b = &ipBucket{tokens: rl.burst, lastSeen: now} + rl.buckets[ip] = b + } + elapsed := now.Sub(b.lastSeen).Seconds() + b.tokens += elapsed * rl.rate + if b.tokens > rl.burst { + b.tokens = rl.burst + } + b.lastSeen = now + if b.tokens < 1 { + return false + } + b.tokens-- + return true +} + +func (rl *rateLimiterState) evictLoop() { + ticker := time.NewTicker(rl.staleAge) + defer ticker.Stop() + for range ticker.C { + rl.mu.Lock() + cutoff := time.Now().Add(-rl.staleAge) + for ip, b := range rl.buckets { + if b.lastSeen.Before(cutoff) { + delete(rl.buckets, ip) + } + } + rl.mu.Unlock() + } +} + +func rateLimit(rl *rateLimiterState, next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Skip rate limiting for health checks. + if r.URL.Path == "/api/health" { + next.ServeHTTP(w, r) + return + } + ip := clientIP(r) + if !rl.allow(ip) { + w.Header().Set("Retry-After", "1") + writeJSON(w, http.StatusTooManyRequests, map[string]string{"error": "rate limit exceeded"}) + return + } + next.ServeHTTP(w, r) + }) +} + +func clientIP(r *http.Request) string { + // Trust X-Forwarded-For from Caddy reverse proxy. + if xff := r.Header.Get("X-Forwarded-For"); xff != "" { + if ip := strings.TrimSpace(strings.SplitN(xff, ",", 2)[0]); ip != "" { + return ip + } + } + if xri := r.Header.Get("X-Real-Ip"); xri != "" { + return strings.TrimSpace(xri) + } + host, _, _ := net.SplitHostPort(r.RemoteAddr) + return host +} diff --git a/internal/collector/api/api_test.go b/internal/collector/api/api_test.go index d4a6127..f2eb891 100644 --- a/internal/collector/api/api_test.go +++ b/internal/collector/api/api_test.go @@ -164,6 +164,59 @@ func TestSearchEmptyQueryReturns400(t *testing.T) { } } +func TestRateLimitReturns429(t *testing.T) { + db := testDB(t) + defer db.Close() + seedAlerts(t, db) + + srv := New(db, ":0", os.Stderr) + handler := srv.srv.Handler + + // Exhaust the burst (30 requests). + for i := 0; i < 30; i++ { + req := httptest.NewRequest("GET", "/api/search?q=europol", nil) + req.RemoteAddr = "10.0.0.1:12345" + w := httptest.NewRecorder() + handler.ServeHTTP(w, req) + if w.Code == http.StatusTooManyRequests { + // Burst may be slightly less than 30 due to token consumption timing. + // Reaching 429 early is fine — the limiter works. + return + } + } + + // The 31st request should be rate limited. + req := httptest.NewRequest("GET", "/api/search?q=europol", nil) + req.RemoteAddr = "10.0.0.1:12345" + w := httptest.NewRecorder() + handler.ServeHTTP(w, req) + if w.Code != http.StatusTooManyRequests { + t.Fatalf("expected 429, got %d", w.Code) + } + if w.Header().Get("Retry-After") == "" { + t.Fatal("expected Retry-After header") + } +} + +func TestRateLimitSkipsHealth(t *testing.T) { + db := testDB(t) + defer db.Close() + + srv := New(db, ":0", os.Stderr) + handler := srv.srv.Handler + + // Even after many requests, health should never be rate limited. + for i := 0; i < 50; i++ { + req := httptest.NewRequest("GET", "/api/health", nil) + req.RemoteAddr = "10.0.0.2:12345" + w := httptest.NewRecorder() + handler.ServeHTTP(w, req) + if w.Code != http.StatusOK { + t.Fatalf("health request %d: expected 200, got %d", i, w.Code) + } + } +} + func TestHealthEndpoint(t *testing.T) { db := testDB(t) defer db.Close() From b236b5393e3c5380d81a5baa04551835f08d5581 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 19:07:14 +0100 Subject: [PATCH 17/58] fix: follow redirects for feeds, strip HTML before translate, UI polish - Always follow HTTP redirects for RSS/Atom feed fetches (302/307 are normal for feeds) instead of treating them as dead sources - Strip HTML and truncate to 2k chars before sending to Google Translate to prevent 413 on feeds with full-page markup in descriptions - Export StripHTML for cross-package use - Left panel: smaller severity numbers, remove duplicate Alerts row, larger Countries/Feeds display, clickable severity filter, zone stats, ">" prefix on capped authority counts, Middle East region - GlobeView: fix map disappearing on force-reload via ResizeObserver - Docker: merge registry into DB on every startup, bump MAX_PER_SOURCE to 40, add dev-sync-registry target, German AA followRedirects --- Makefile | 3 + docker-compose.yml | 2 +- docker/collector-entrypoint.sh | 7 ++ internal/collector/parse/fbi.go | 4 +- internal/collector/parse/html.go | 6 +- internal/collector/run/run.go | 8 +- internal/collector/translate/google.go | 10 ++ registry/source_registry.json | 1 + src/components/FeedDirectory.tsx | 146 ++++++++++++++++--------- src/components/GlobeView.tsx | 10 ++ src/components/Header.tsx | 4 +- src/lib/regions.ts | 11 ++ 12 files changed, 152 insertions(+), 60 deletions(-) diff --git a/Makefile b/Makefile index a61f9c4..cb6eaed 100644 --- a/Makefile +++ b/Makefile @@ -140,6 +140,9 @@ dev-restart: ## Restart the local dev stack (prunes old images first) @echo "EUOSINT available at http://localhost:$${EUOSINT_HTTP_PORT:-8080}" @open "http://localhost:$${EUOSINT_HTTP_PORT:-8080}" +dev-sync-registry: ## Merge source_registry.json into the running DB (adds new feeds) + $(DOCKER_COMPOSE) exec collector euosint-collector --source-db /data/sources.db --curated-seed /app/registry/source_registry.json --source-db-merge-registry + dev-logs: ## Tail local dev stack logs $(DOCKER_COMPOSE) logs -f --tail=200 diff --git a/docker-compose.yml b/docker-compose.yml index 1ba93ab..941340a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -26,7 +26,7 @@ services: - /data/source_dead_letter.json environment: INTERVAL_MS: "900000" - MAX_PER_SOURCE: "20" + MAX_PER_SOURCE: "40" MISSING_PERSON_RELEVANCE_THRESHOLD: "0" FAIL_ON_CRITICAL_SOURCE_GAP: "0" CRITICAL_SOURCE_PREFIXES: "interpol-red,interpol-yellow" diff --git a/docker/collector-entrypoint.sh b/docker/collector-entrypoint.sh index 5d8bd36..2579a10 100644 --- a/docker/collector-entrypoint.sh +++ b/docker/collector-entrypoint.sh @@ -29,4 +29,11 @@ if [ ! -f /data/sources.db ]; then fi fi +# Always merge the baked-in JSON registry into the DB on startup. +# MergeRegistry upserts only — it adds new sources and updates existing +# ones but never deletes discovered or runtime-added sources. +# This ensures new feeds (FBI API, travel warnings, etc.) from image +# updates are picked up without manual intervention. +euosint-collector --source-db /data/sources.db --curated-seed /app/registry/source_registry.json --source-db-merge-registry + exec euosint-collector "$@" diff --git a/internal/collector/parse/fbi.go b/internal/collector/parse/fbi.go index 3d9e0b9..ab4c2df 100644 --- a/internal/collector/parse/fbi.go +++ b/internal/collector/parse/fbi.go @@ -88,7 +88,7 @@ func ParseFBIWanted(body []byte) ([]FeedItem, int, error) { func buildFBISummary(entry FBIWantedEntry) string { parts := []string{} - if desc := stripHTML(entry.Description); desc != "" { + if desc := StripHTML(entry.Description); desc != "" { parts = append(parts, desc) } if entry.Nationality != "" { @@ -101,7 +101,7 @@ func buildFBISummary(entry FBIWantedEntry) string { parts = append(parts, "Aliases: "+strings.Join(entry.Aliases, ", ")) } if entry.RewardText != "" { - parts = append(parts, "Reward: "+stripHTML(entry.RewardText)) + parts = append(parts, "Reward: "+StripHTML(entry.RewardText)) } return strings.Join(parts, ". ") } diff --git a/internal/collector/parse/html.go b/internal/collector/parse/html.go index 5d1e3b8..af7f962 100644 --- a/internal/collector/parse/html.go +++ b/internal/collector/parse/html.go @@ -34,7 +34,7 @@ func ParseHTMLAnchors(body string, baseURL string) []FeedItem { if err != nil { continue } - title := stripHTML(match[2]) + title := StripHTML(match[2]) if len(title) < 8 { continue } @@ -48,7 +48,9 @@ func ParseHTMLAnchors(body string, baseURL string) []FeedItem { return out } -func stripHTML(value string) string { +// StripHTML removes script/style tags, strips remaining HTML tags, +// unescapes entities, and normalizes whitespace. +func StripHTML(value string) string { value = scriptStripRe.ReplaceAllString(value, " ") value = tagStripRe.ReplaceAllString(value, " ") value = html.UnescapeString(value) diff --git a/internal/collector/run/run.go b/internal/collector/run/run.go index 9ba2fed..6176699 100644 --- a/internal/collector/run/run.go +++ b/internal/collector/run/run.go @@ -598,9 +598,11 @@ func fetchWithFallbackURL(ctx context.Context, fetcher fetch.Fetcher, source mod candidates = append(candidates, source.FeedURL) } candidates = append(candidates, source.FeedURLs...) + // Always follow redirects for feed fetches — 301/302/307 are normal + // for RSS/Atom feeds (HTTP→HTTPS, www→non-www, CDN routing, etc.). var lastErr error for _, candidate := range candidates { - body, err := fetcher.Text(ctx, candidate, source.FollowRedirects, accept) + body, err := fetcher.Text(ctx, candidate, true, accept) if err == nil { return body, candidate, nil } @@ -751,7 +753,9 @@ func classifySourceError(err error) (string, bool, string) { case strings.Contains(msg, "status 404"), strings.Contains(msg, "status 410"): return "not_found", true, "dead_letter" case strings.Contains(msg, "status 301"), strings.Contains(msg, "status 302"), strings.Contains(msg, "status 307"), strings.Contains(msg, "status 308"): - return "redirect", true, "dead_letter" + // Redirects should be followed automatically — if we still see + // one here it means the chain exceeded 10 hops. + return "redirect", false, "retry" case strings.Contains(msg, "status 403"): return "blocked", true, "dead_letter" case strings.Contains(msg, "response too large"): diff --git a/internal/collector/translate/google.go b/internal/collector/translate/google.go index 6a4a6e4..9dcee3d 100644 --- a/internal/collector/translate/google.go +++ b/internal/collector/translate/google.go @@ -15,6 +15,10 @@ import ( "github.com/scalytics/euosint/internal/collector/parse" ) +// maxTranslateChars is the maximum character count sent to Google Translate +// per field. The free gtx endpoint returns 413 for payloads above ~5 KB. +const maxTranslateChars = 2000 + var nonLatinRE = regexp.MustCompile(`[\p{Han}\p{Hangul}\p{Cyrillic}\p{Arabic}\p{Thai}]`) func Batch(ctx context.Context, client *fetch.Client, items []parse.FeedItem) ([]parse.FeedItem, error) { @@ -40,10 +44,16 @@ func Batch(ctx context.Context, client *fetch.Client, items []parse.FeedItem) ([ } func toEnglish(ctx context.Context, client *fetch.Client, text string) (string, error) { + // Strip HTML (RSS descriptions often contain full page markup) and truncate + // to avoid 413 from the free Google Translate endpoint. + text = parse.StripHTML(text) text = strings.TrimSpace(text) if text == "" { return text, nil } + if len(text) > maxTranslateChars { + text = text[:maxTranslateChars] + } endpoint := "https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=en&dt=t&q=" + url.QueryEscape(text) body, err := client.Text(ctx, endpoint, true, "application/json") if err != nil { diff --git a/registry/source_registry.json b/registry/source_registry.json index 8de5be3..b97652b 100644 --- a/registry/source_registry.json +++ b/registry/source_registry.json @@ -2761,6 +2761,7 @@ }, { "type": "travelwarning-json", + "followRedirects": true, "source": { "source_id": "de-aa-travel", "authority_name": "German Federal Foreign Office", diff --git a/src/components/FeedDirectory.tsx b/src/components/FeedDirectory.tsx index 7a6eaa6..c949e15 100644 --- a/src/components/FeedDirectory.tsx +++ b/src/components/FeedDirectory.tsx @@ -19,6 +19,7 @@ import { categoryLabels, categoryBadge, categoryOrder } from "@/lib/severity"; import { alertMatchesRegionFilter } from "@/lib/regions"; type View = "overview" | "feeds" | "authorities" | "health"; +type SeverityFilter = "critical" | "high" | null; interface Props { view: View; @@ -46,6 +47,7 @@ export function FeedDirectory({ }: Props) { const sources = sourceHealth?.sources ?? []; const [now, setNow] = useState(() => Date.now()); + const [severityFilter, setSeverityFilter] = useState(null); useEffect(() => { const timer = window.setInterval(() => setNow(Date.now()), 60_000); @@ -59,6 +61,12 @@ export function FeedDirectory({ [alerts, regionFilter], ); + // Alerts after optional severity filter (for downstream stats). + const filteredAlerts = useMemo(() => { + if (!severityFilter) return regionAlerts; + return regionAlerts.filter((a) => a.severity === severityFilter); + }, [regionAlerts, severityFilter]); + /* ── Derived stats (all from region-scoped alerts) ─────────────── */ const severityCounts = useMemo(() => { @@ -71,35 +79,46 @@ export function FeedDirectory({ const countryCounts = useMemo(() => { const map = new Map(); - for (const a of regionAlerts) { + for (const a of filteredAlerts) { const key = a.source.country_code; const existing = map.get(key); if (existing) existing.count++; else map.set(key, { name: a.source.country, code: key, count: 1 }); } - return [...map.values()].sort((a, b) => b.count - a.count).slice(0, 10); - }, [regionAlerts]); + return [...map.values()].sort((a, b) => b.count - a.count).slice(0, 12); + }, [filteredAlerts]); const categoryCounts = useMemo(() => { const counts: Partial> = {}; - for (const a of regionAlerts) { + for (const a of filteredAlerts) { counts[a.category] = (counts[a.category] ?? 0) + 1; } return categoryOrder .filter((cat) => (counts[cat] ?? 0) > 0) .map((cat) => ({ category: cat, count: counts[cat]! })); - }, [regionAlerts]); + }, [filteredAlerts]); const topAuthorities = useMemo(() => { - const map = new Map(); - for (const a of regionAlerts) { + const map = new Map(); + for (const a of filteredAlerts) { const key = a.source_id; const existing = map.get(key); if (existing) existing.count++; - else map.set(key, { name: a.source.authority_name, sourceId: key, count: 1 }); + else map.set(key, { name: a.source.authority_name, sourceId: key, count: 1, maxItems: 0 }); } - return [...map.values()].sort((a, b) => b.count - a.count).slice(0, 10); - }, [regionAlerts]); + return [...map.values()].sort((a, b) => b.count - a.count).slice(0, 12); + }, [filteredAlerts]); + + /* ── Zone summary stats ─────────────────────────────────────────── */ + const zoneSummary = useMemo(() => { + const uniqueCountries = new Set(filteredAlerts.map((a) => a.source.country_code)); + const uniqueFeeds = new Set(filteredAlerts.map((a) => a.source_id)); + return { + alerts: filteredAlerts.length, + countries: uniqueCountries.size, + feeds: uniqueFeeds.size, + }; + }, [filteredAlerts]); const toggleSource = (sourceId: string) => { if (selectedSourceIds.includes(sourceId)) { @@ -148,52 +167,67 @@ export function FeedDirectory({
{/* Header */}
-
- - Intelligence Overview +
+
+ + {regionFilter === "all" ? "Global Overview" : regionFilter.startsWith("country:") ? regionFilter.slice(8) : regionFilter} +
+ {severityFilter && ( + + )}
- {/* ── Severity breakdown ──────────────────────────────────── */} + {/* ── Severity breakdown (clickable) ──────────────────────── */}
- {[ - { label: "Critical", value: severityCounts.critical, icon: AlertTriangle, tone: "text-rose-300" }, - { label: "High", value: severityCounts.high, icon: ShieldAlert, tone: "text-amber-300" }, - { label: "Active", value: regionAlerts.filter((a) => a.status === "active").length, icon: Activity, tone: "text-emerald-300" }, - ].map((card) => ( -
a.status === "active").length, icon: Activity, tone: "text-emerald-300", border: "" }, + ]).map((card) => ( +
+ ))}
- {/* ── Feed health summary ─────────────────────────────────── */} + {/* ── Zone summary stats ──────────────────────────────────── */}
-
- - - {new Set(regionAlerts.map((a) => a.source.country_code)).size} - +
+ + {zoneSummary.countries}
Countries
-
- - - {sourceHealth?.sources_ok ?? 0}/{sourceHealth?.total_sources ?? 0} - -
-
- Feeds OK +
+ + {zoneSummary.feeds}
+
Feeds
@@ -213,21 +247,29 @@ export function FeedDirectory({ All feeds (clear filter) )} - {topAuthorities.map((auth) => ( - - ))} + {topAuthorities.map((auth) => { + // Show ">" prefix when count looks like it hit a per-source cap + // (common caps: 15, 20, 40, 60, 80, 100). + const commonCaps = [15, 20, 40, 60, 80, 100]; + const likelyCapped = commonCaps.includes(auth.count); + return ( + + ); + })}
diff --git a/src/components/GlobeView.tsx b/src/components/GlobeView.tsx index eecfadd..72296e8 100644 --- a/src/components/GlobeView.tsx +++ b/src/components/GlobeView.tsx @@ -129,7 +129,17 @@ export function GlobeView({ mapRef.current = map; clusterRef.current = cluster; + // Leaflet needs a correctly-sized container. On force-reload the + // layout may not yet be computed when the map initialises, giving it + // 0×0 dimensions. A ResizeObserver fixes this by calling + // invalidateSize() whenever the container gets its real size. + const ro = new ResizeObserver(() => { + map.invalidateSize(); + }); + ro.observe(containerRef.current); + return () => { + ro.disconnect(); map.remove(); mapRef.current = null; clusterRef.current = null; diff --git a/src/components/Header.tsx b/src/components/Header.tsx index a6f3054..d1d77e7 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -7,6 +7,7 @@ import { useEffect, useMemo, useRef, useState } from "react"; import { Globe2, Radar, Search, Shield, X } from "lucide-react"; import type { Alert } from "@/types/alert"; +import { alertMatchesRegionFilter } from "@/lib/regions"; type MenuView = "overview" | "feeds" | "authorities" | "health"; @@ -29,6 +30,7 @@ const REGIONS = [ "North America", "South America", "Africa", + "Middle East", "Asia", "Oceania", "Caribbean", @@ -354,7 +356,7 @@ function RegionSearch({ value: r, label: r === "all" ? "All regions" : r, type: "region" as const, - count: r === "all" ? alerts.length : alerts.filter((a) => a.source.region === r).length, + count: r === "all" ? alerts.length : alerts.filter((a) => alertMatchesRegionFilter(a, r)).length, })); const countryMap = new Map(); diff --git a/src/lib/regions.ts b/src/lib/regions.ts index 6eeaabf..48db0af 100644 --- a/src/lib/regions.ts +++ b/src/lib/regions.ts @@ -50,6 +50,11 @@ export function latLngToRegion(lat: number, lng: number): string | null { return null; } +export const MIDDLE_EAST_CODES = new Set([ + "AE", "BH", "CY", "EG", "IL", "IQ", "IR", "JO", "KW", "LB", + "OM", "PS", "QA", "SA", "SY", "TR", "YE", +]); + export function alertMatchesRegionFilter(alert: Alert, regionFilter: string): boolean { if (regionFilter === "all") return true; if (regionFilter.startsWith("country:")) { @@ -61,5 +66,11 @@ export function alertMatchesRegionFilter(alert: Alert, regionFilter: string): bo inBounds(alert.lat, alert.lng, CARIBBEAN_INTERACTION_BOUNDS) ); } + if (regionFilter === "Middle East") { + return ( + alert.source.region === "Middle East" || + MIDDLE_EAST_CODES.has(alert.source.country_code) + ); + } return alert.source.region === regionFilter; } From b1fd3ef3380e6127331b2d7fc7546fedebda8483 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 19:08:00 +0100 Subject: [PATCH 18/58] chore: add test-interpol CLI utility for probing HTML sources --- cmd/test-interpol/main.go | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 cmd/test-interpol/main.go diff --git a/cmd/test-interpol/main.go b/cmd/test-interpol/main.go new file mode 100644 index 0000000..d508459 --- /dev/null +++ b/cmd/test-interpol/main.go @@ -0,0 +1,51 @@ +package main + +import ( + "context" + "fmt" + "strings" + "time" + "github.com/scalytics/euosint/internal/collector/config" + "github.com/scalytics/euosint/internal/collector/fetch" +) + +func main() { + cfg := config.Default() + client := fetch.New(cfg) + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + + // Fetch ICPC wanted page + body, err := client.Text(ctx, "https://icpc.gov.ng/wanted-persons/", true, "text/html") + if err != nil { + fmt.Println("ERROR:", err) + return + } + s := string(body) + fmt.Printf("Got %d bytes\n", len(s)) + // Find person-related patterns + for _, pattern := range []string{"wanted", "person", "card", "grid", "profile", "name", "offence", "offense"} { + idx := 0 + count := 0 + lower := strings.ToLower(s) + for { + i := strings.Index(lower[idx:], pattern) + if i < 0 { break } + idx += i + len(pattern) + count++ + } + if count > 0 { + fmt.Printf(" '%s' found %d times\n", pattern, count) + } + } + // Show a chunk around "wanted" context + lower := strings.ToLower(s) + if i := strings.Index(lower, "wanted-person"); i >= 0 { + start := i - 200 + if start < 0 { start = 0 } + end := i + 500 + if end > len(s) { end = len(s) } + fmt.Println("\n--- CONTEXT ---") + fmt.Println(s[start:end]) + } +} From 6f354bcba197c46d31bf728b4a47f3a0554df749 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 19:09:40 +0100 Subject: [PATCH 19/58] Revert "chore: add test-interpol CLI utility for probing HTML sources" This reverts commit b1fd3ef3380e6127331b2d7fc7546fedebda8483. --- cmd/test-interpol/main.go | 51 --------------------------------------- 1 file changed, 51 deletions(-) delete mode 100644 cmd/test-interpol/main.go diff --git a/cmd/test-interpol/main.go b/cmd/test-interpol/main.go deleted file mode 100644 index d508459..0000000 --- a/cmd/test-interpol/main.go +++ /dev/null @@ -1,51 +0,0 @@ -package main - -import ( - "context" - "fmt" - "strings" - "time" - "github.com/scalytics/euosint/internal/collector/config" - "github.com/scalytics/euosint/internal/collector/fetch" -) - -func main() { - cfg := config.Default() - client := fetch.New(cfg) - ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) - defer cancel() - - // Fetch ICPC wanted page - body, err := client.Text(ctx, "https://icpc.gov.ng/wanted-persons/", true, "text/html") - if err != nil { - fmt.Println("ERROR:", err) - return - } - s := string(body) - fmt.Printf("Got %d bytes\n", len(s)) - // Find person-related patterns - for _, pattern := range []string{"wanted", "person", "card", "grid", "profile", "name", "offence", "offense"} { - idx := 0 - count := 0 - lower := strings.ToLower(s) - for { - i := strings.Index(lower[idx:], pattern) - if i < 0 { break } - idx += i + len(pattern) - count++ - } - if count > 0 { - fmt.Printf(" '%s' found %d times\n", pattern, count) - } - } - // Show a chunk around "wanted" context - lower := strings.ToLower(s) - if i := strings.Index(lower, "wanted-person"); i >= 0 { - start := i - 200 - if start < 0 { start = 0 } - end := i + 500 - if end > len(s) { end = len(s) } - fmt.Println("\n--- CONTEXT ---") - fmt.Println(s[start:end]) - } -} From 2ca11671ee18afa9ffeaaf082b33acd42fdf5110 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 19:10:23 +0100 Subject: [PATCH 20/58] chore: gitignore throwaway cmd/test-* utilities --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 453d796..4aa4548 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ dist-ssr/ coverage/ .tmp/ /euosint-collector +cmd/test-*/ # Runtime logs logs/ From 5d027d647450e26738701e9fddd488623595ab6f Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 19:14:22 +0100 Subject: [PATCH 21/58] reject BSI NESAS source and filter rejected entries in JSON loader BSI NESAS is a product certification feed (NESAS audit/evaluation docs), not security advisories. Mark it as rejected in the registry and add promotion_status filtering to normalizeAll() so the JSON loader respects rejection status the same way the SQLite loader does. --- internal/collector/registry/registry.go | 3 +++ registry/source_registry.json | 2 ++ src/components/Header.tsx | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/internal/collector/registry/registry.go b/internal/collector/registry/registry.go index 7acffd1..0a8aa0a 100644 --- a/internal/collector/registry/registry.go +++ b/internal/collector/registry/registry.go @@ -78,6 +78,9 @@ func normalizeAll(raw []model.RegistrySource) []model.RegistrySource { seen := make(map[string]struct{}, len(raw)) out := make([]model.RegistrySource, 0, len(raw)) for _, entry := range raw { + if strings.ToLower(strings.TrimSpace(entry.PromotionStatus)) == "rejected" { + continue + } normalized, ok := normalize(entry) if !ok { continue diff --git a/registry/source_registry.json b/registry/source_registry.json index b97652b..2164c59 100644 --- a/registry/source_registry.json +++ b/registry/source_registry.json @@ -2287,6 +2287,8 @@ }, { "type": "rss", + "promotion_status": "rejected", + "rejection_reason": "Product certification feed (NESAS audit/evaluation docs), not security advisories", "source": { "source_id": "bsi-nesas", "authority_name": "BSI NESAS", diff --git a/src/components/Header.tsx b/src/components/Header.tsx index d1d77e7..41fc19d 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -437,7 +437,7 @@ function RegionSearch({ type="text" value={query} onChange={(e) => setQuery(e.target.value)} - placeholder="Search regions, countries\u2026" + placeholder="Search regions, countries..." className="w-full bg-transparent pl-7 pr-7 py-1.5 text-xs text-siem-text placeholder:text-siem-muted/60 outline-none" /> {query && ( From 7b9569ccefdd44d80b81aebfd66526325d734201 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 19:26:41 +0100 Subject: [PATCH 22/58] reject dead FBI News RSS feed, fix global feed count FBI removed their RSS feeds; news/press releases are not available via the Wanted API either. Mark fbi-news as rejected. Fix FeedDirectory global overview to use source-health total instead of counting only sources that produced alerts. --- registry/source_registry.json | 2 ++ src/components/FeedDirectory.tsx | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/registry/source_registry.json b/registry/source_registry.json index 2164c59..6aaadfd 100644 --- a/registry/source_registry.json +++ b/registry/source_registry.json @@ -3472,6 +3472,8 @@ }, { "type": "rss", + "promotion_status": "rejected", + "rejection_reason": "FBI removed RSS feeds; news/press releases not available via API (API only serves wanted persons). Covered by fbi-wanted, fbi-mostwanted, fbi-seeking, fbi-kidnappings.", "source": { "source_id": "fbi-news", "authority_name": "FBI News", diff --git a/src/components/FeedDirectory.tsx b/src/components/FeedDirectory.tsx index c949e15..b31f256 100644 --- a/src/components/FeedDirectory.tsx +++ b/src/components/FeedDirectory.tsx @@ -113,12 +113,18 @@ export function FeedDirectory({ const zoneSummary = useMemo(() => { const uniqueCountries = new Set(filteredAlerts.map((a) => a.source.country_code)); const uniqueFeeds = new Set(filteredAlerts.map((a) => a.source_id)); + // For global view, use the health document's total which includes sources + // that returned 0 alerts (errors, empty feeds, etc.). + const feedCount = + regionFilter === "all" && !severityFilter && sources.length > 0 + ? sources.length + : uniqueFeeds.size; return { alerts: filteredAlerts.length, countries: uniqueCountries.size, - feeds: uniqueFeeds.size, + feeds: feedCount, }; - }, [filteredAlerts]); + }, [filteredAlerts, regionFilter, severityFilter, sources]); const toggleSource = (sourceId: string) => { if (selectedSourceIds.includes(sourceId)) { From d58bc2aac3b58afae320f59c8d58013176469a33 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 19:37:34 +0100 Subject: [PATCH 23/58] lift severity filter to App, replace Active with Conflict MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Critical/High buttons now filter the map and alert feed globally instead of only affecting left-panel stats. Third box shows conflict monitoring count (ACLED etc.) and toggles that category filter. Remove the Clear button — click again to deselect. --- src/App.tsx | 12 +++++-- src/components/FeedDirectory.tsx | 56 ++++++++++++++------------------ 2 files changed, 35 insertions(+), 33 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 491a581..8b83a99 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -14,7 +14,9 @@ import { useAlerts } from "@/hooks/useAlerts"; import { useSearch } from "@/hooks/useSearch"; import { useSourceHealth } from "@/hooks/useSourceHealth"; import { alertMatchesRegionFilter } from "@/lib/regions"; -import type { AlertCategory } from "@/types/alert"; +import type { AlertCategory, Severity } from "@/types/alert"; + +type SeverityFilter = Severity | null; const SOURCE_SELECTION_COOKIE = "euosint_selected_sources"; @@ -48,6 +50,7 @@ export default function App() { const [selectedId, setSelectedId] = useState(null); const [selectedSourceIds, setSelectedSourceIds] = useState([]); const [categoryFilter, setCategoryFilter] = useState("all"); + const [severityFilter, setSeverityFilter] = useState(null); const [regionFilter, setRegionFilter] = useState("Europe"); const { query: searchQuery, setQuery: setSearchQuery, results: searchResults, isApiAvailable } = useSearch(); const [visibleAlertIds, setVisibleAlertIds] = useState([]); @@ -124,8 +127,11 @@ export default function App() { if (categoryFilter !== "all") { filtered = filtered.filter((alert) => alert.category === categoryFilter); } + if (severityFilter) { + filtered = filtered.filter((alert) => alert.severity === severityFilter); + } return filtered; - }, [categoryFilter, regionScopedAlerts, selectedSourceIds]); + }, [categoryFilter, regionScopedAlerts, selectedSourceIds, severityFilter]); const handleCountrySelect = useCallback((countryCode: string) => { const nextRegion = `country:${countryCode}`; @@ -207,6 +213,8 @@ export default function App() { onSelectCategory={setCategoryFilter} regionFilter={regionFilter} onSelectCountry={handleCountrySelect} + severityFilter={severityFilter} + onSeverityFilterChange={setSeverityFilter} />
diff --git a/src/components/FeedDirectory.tsx b/src/components/FeedDirectory.tsx index b31f256..2d02740 100644 --- a/src/components/FeedDirectory.tsx +++ b/src/components/FeedDirectory.tsx @@ -6,7 +6,6 @@ import { useEffect, useMemo, useState } from "react"; import { - Activity, AlertTriangle, Globe2, Radar, @@ -32,6 +31,8 @@ interface Props { onSelectCategory: (category: AlertCategory | "all") => void; regionFilter: string; onSelectCountry: (countryCode: string) => void; + severityFilter: SeverityFilter; + onSeverityFilterChange: (filter: SeverityFilter) => void; } export function FeedDirectory({ @@ -44,10 +45,11 @@ export function FeedDirectory({ onSelectCategory, regionFilter, onSelectCountry, + severityFilter, + onSeverityFilterChange, }: Props) { const sources = sourceHealth?.sources ?? []; const [now, setNow] = useState(() => Date.now()); - const [severityFilter, setSeverityFilter] = useState(null); useEffect(() => { const timer = window.setInterval(() => setNow(Date.now()), 60_000); @@ -61,12 +63,6 @@ export function FeedDirectory({ [alerts, regionFilter], ); - // Alerts after optional severity filter (for downstream stats). - const filteredAlerts = useMemo(() => { - if (!severityFilter) return regionAlerts; - return regionAlerts.filter((a) => a.severity === severityFilter); - }, [regionAlerts, severityFilter]); - /* ── Derived stats (all from region-scoped alerts) ─────────────── */ const severityCounts = useMemo(() => { @@ -79,52 +75,52 @@ export function FeedDirectory({ const countryCounts = useMemo(() => { const map = new Map(); - for (const a of filteredAlerts) { + for (const a of regionAlerts) { const key = a.source.country_code; const existing = map.get(key); if (existing) existing.count++; else map.set(key, { name: a.source.country, code: key, count: 1 }); } return [...map.values()].sort((a, b) => b.count - a.count).slice(0, 12); - }, [filteredAlerts]); + }, [regionAlerts]); const categoryCounts = useMemo(() => { const counts: Partial> = {}; - for (const a of filteredAlerts) { + for (const a of regionAlerts) { counts[a.category] = (counts[a.category] ?? 0) + 1; } return categoryOrder .filter((cat) => (counts[cat] ?? 0) > 0) .map((cat) => ({ category: cat, count: counts[cat]! })); - }, [filteredAlerts]); + }, [regionAlerts]); const topAuthorities = useMemo(() => { const map = new Map(); - for (const a of filteredAlerts) { + for (const a of regionAlerts) { const key = a.source_id; const existing = map.get(key); if (existing) existing.count++; else map.set(key, { name: a.source.authority_name, sourceId: key, count: 1, maxItems: 0 }); } return [...map.values()].sort((a, b) => b.count - a.count).slice(0, 12); - }, [filteredAlerts]); + }, [regionAlerts]); /* ── Zone summary stats ─────────────────────────────────────────── */ const zoneSummary = useMemo(() => { - const uniqueCountries = new Set(filteredAlerts.map((a) => a.source.country_code)); - const uniqueFeeds = new Set(filteredAlerts.map((a) => a.source_id)); + const uniqueCountries = new Set(regionAlerts.map((a) => a.source.country_code)); + const uniqueFeeds = new Set(regionAlerts.map((a) => a.source_id)); // For global view, use the health document's total which includes sources // that returned 0 alerts (errors, empty feeds, etc.). const feedCount = - regionFilter === "all" && !severityFilter && sources.length > 0 + regionFilter === "all" && sources.length > 0 ? sources.length : uniqueFeeds.size; return { - alerts: filteredAlerts.length, + alerts: regionAlerts.length, countries: uniqueCountries.size, feeds: feedCount, }; - }, [filteredAlerts, regionFilter, severityFilter, sources]); + }, [regionAlerts, regionFilter, sources]); const toggleSource = (sourceId: string) => { if (selectedSourceIds.includes(sourceId)) { @@ -179,13 +175,9 @@ export function FeedDirectory({ {regionFilter === "all" ? "Global Overview" : regionFilter.startsWith("country:") ? regionFilter.slice(8) : regionFilter}
{severityFilter && ( - + + {severityFilter} + )}
@@ -196,21 +188,23 @@ export function FeedDirectory({ {([ { key: "critical" as SeverityFilter, label: "Critical", value: severityCounts.critical, icon: AlertTriangle, tone: "text-rose-300", border: "border-rose-400/40" }, { key: "high" as SeverityFilter, label: "High", value: severityCounts.high, icon: ShieldAlert, tone: "text-amber-300", border: "border-amber-400/40" }, - { key: null as SeverityFilter, label: "Active", value: regionAlerts.filter((a) => a.status === "active").length, icon: Activity, tone: "text-emerald-300", border: "" }, + { key: null as SeverityFilter, label: "Conflict", value: regionAlerts.filter((a) => a.category === "conflict_monitoring").length, icon: Radar, tone: "text-orange-300", border: "border-orange-400/40" }, ]).map((card) => (
- + {zoneSummary.feeds}
Feeds
From 05bafc5f7c2cfb497cd44eb8d6f467f4fccadcfb Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 20:52:09 +0100 Subject: [PATCH 26/58] add humanitarian and peacekeeping feeds, reject broken sources MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New sources: - UN Peacekeeping (Blue Helmets) — mission/deployment updates - UN OCHA — humanitarian crisis coordination - UN News Peace & Security — conflict/peacekeeping coverage - UN News Refugees & Migrants — displacement/migration intel - UN News Humanitarian Aid — aid operations and tasking - ICRC Humanitarian Law & Policy — IHL and conflict law - ICRC Field Operations — Israel/Gaza/West Bank ops reporting Rejected (feeds dead, no alternative): - ICRC News (404), UNHCR (403), WFP (403), ICRC Family Links (403) --- registry/source_registry.json | 127 ++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/registry/source_registry.json b/registry/source_registry.json index ab1881d..190c72d 100644 --- a/registry/source_registry.json +++ b/registry/source_registry.json @@ -2148,6 +2148,8 @@ }, { "type": "html-list", + "promotion_status": "rejected", + "rejection_reason": "ICRC Family Links blocks all automated access (403)", "followRedirects": true, "source": { "source_id": "icrc-family-links", @@ -2876,6 +2878,8 @@ }, { "type": "rss", + "promotion_status": "rejected", + "rejection_reason": "ICRC removed main RSS feed; replaced by icrc-ihl and icrc-field-ops", "source": { "source_id": "icrc-news", "authority_name": "ICRC News", @@ -2893,6 +2897,42 @@ }, { "type": "rss", + "source": { + "source_id": "icrc-ihl", + "authority_name": "ICRC Humanitarian Law & Policy", + "country": "Switzerland", + "country_code": "CH", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://blogs.icrc.org/law-and-policy" + }, + "feed_url": "https://blogs.icrc.org/law-and-policy/feed/", + "category": "humanitarian_security", + "region_tag": "INT", + "lat": 46.22, + "lng": 6.14 + }, + { + "type": "rss", + "source": { + "source_id": "icrc-field-ops", + "authority_name": "ICRC Field Operations", + "country": "Switzerland", + "country_code": "CH", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://blogs.icrc.org/ilot" + }, + "feed_url": "https://blogs.icrc.org/ilot/feed/", + "category": "humanitarian_security", + "region_tag": "INT", + "lat": 46.22, + "lng": 6.14 + }, + { + "type": "rss", + "promotion_status": "rejected", + "rejection_reason": "UNHCR blocks RSS access (403); replaced by un-refugees feed", "source": { "source_id": "unhcr-news", "authority_name": "UNHCR News", @@ -2961,6 +3001,93 @@ }, { "type": "rss", + "source": { + "source_id": "un-peacekeeping", + "authority_name": "UN Peacekeeping (Blue Helmets)", + "country": "United States", + "country_code": "US", + "region": "International", + "authority_type": "national_security", + "base_url": "https://peacekeeping.un.org" + }, + "feed_url": "https://peacekeeping.un.org/en/rss.xml", + "category": "conflict_monitoring", + "region_tag": "INT", + "lat": 40.75, + "lng": -73.97 + }, + { + "type": "rss", + "source": { + "source_id": "unocha", + "authority_name": "UN OCHA", + "country": "United States", + "country_code": "US", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://www.unocha.org" + }, + "feed_url": "https://www.unocha.org/rss.xml", + "category": "humanitarian_security", + "region_tag": "INT", + "lat": 40.75, + "lng": -73.97 + }, + { + "type": "rss", + "source": { + "source_id": "un-peace-security", + "authority_name": "UN News Peace & Security", + "country": "United States", + "country_code": "US", + "region": "International", + "authority_type": "national_security", + "base_url": "https://news.un.org" + }, + "feed_url": "https://news.un.org/feed/subscribe/en/news/topic/peace-and-security/feed/rss.xml", + "category": "conflict_monitoring", + "region_tag": "INT", + "lat": 40.75, + "lng": -73.97 + }, + { + "type": "rss", + "source": { + "source_id": "un-refugees", + "authority_name": "UN News Refugees & Migrants", + "country": "United States", + "country_code": "US", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://news.un.org" + }, + "feed_url": "https://news.un.org/feed/subscribe/en/news/topic/migrants-and-refugees/feed/rss.xml", + "category": "humanitarian_security", + "region_tag": "INT", + "lat": 40.75, + "lng": -73.97 + }, + { + "type": "rss", + "source": { + "source_id": "un-humanitarian-aid", + "authority_name": "UN News Humanitarian Aid", + "country": "United States", + "country_code": "US", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://news.un.org" + }, + "feed_url": "https://news.un.org/feed/subscribe/en/news/topic/humanitarian-aid/feed/rss.xml", + "category": "humanitarian_tasking", + "region_tag": "INT", + "lat": 40.75, + "lng": -73.97 + }, + { + "type": "rss", + "promotion_status": "rejected", + "rejection_reason": "WFP blocks RSS access (403); no alternative operational feed available", "source": { "source_id": "wfp-news", "authority_name": "World Food Programme News", From 2861b950233aab671e25b8514e67e88c968ae0bf Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 20:57:00 +0100 Subject: [PATCH 27/58] fix OIJ nav scraping and NCMEC broken titles OIJ Costa Rica: remove "oij" from include_keywords (matched every URL on the domain), drop root URL from feed_urls to avoid scraping navigation. Tighten keywords to actual missing person terms. NCMEC: their RSS emits titles like ": Name (State)" with a leading colon. Prefix with "Missing" so it reads "Missing: Name (State)". --- internal/collector/normalize/normalize.go | 6 ++++++ registry/source_registry.json | 9 +++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/internal/collector/normalize/normalize.go b/internal/collector/normalize/normalize.go index 4b5f848..89e1b75 100644 --- a/internal/collector/normalize/normalize.go +++ b/internal/collector/normalize/normalize.go @@ -304,6 +304,12 @@ func StaticInterpolEntry(now time.Time) model.Alert { } func baseAlert(ctx Context, meta model.RegistrySource, title string, link string, publishedAt time.Time) model.Alert { + title = strings.TrimSpace(title) + // Fix broken NCMEC-style titles that start with ": Name (State)". + if strings.HasPrefix(title, ": ") { + title = "Missing" + title + } + baseLat, baseLng := meta.Lat, meta.Lng source := meta.Source diff --git a/registry/source_registry.json b/registry/source_registry.json index 190c72d..099c280 100644 --- a/registry/source_registry.json +++ b/registry/source_registry.json @@ -1995,8 +1995,7 @@ "feed_url": "https://sitiooij.poder-judicial.go.cr/index.php/oficinas-y-departamentos/desaparecidos", "feed_urls": [ "https://sitiooij.poder-judicial.go.cr/index.php/oficinas-y-departamentos/desaparecidos", - "https://sitiooij.poder-judicial.go.cr/index.php/noticias", - "https://sitiooij.poder-judicial.go.cr" + "https://sitiooij.poder-judicial.go.cr/index.php/noticias" ], "category": "missing_person", "region_tag": "CR", @@ -2005,11 +2004,9 @@ "max_items": 120, "include_keywords": [ "desaparec", - "persona", + "no localiza", "se busca", - "informacion", - "auxilio", - "oij" + "auxilio" ], "exclude_keywords": [ "licitacion", From 45e44bbaf7a27a7a7ec0a781340042fad3901505 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 20:58:38 +0100 Subject: [PATCH 28/58] reset navigator selection on region or category change When switching regions via header shortcuts or the scope dropdown, the active navigator group now resets so the first group in the new region is auto-selected instead of sticking to the old selection. --- src/components/AlertFeed.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/AlertFeed.tsx b/src/components/AlertFeed.tsx index 963ac0a..e953a9c 100644 --- a/src/components/AlertFeed.tsx +++ b/src/components/AlertFeed.tsx @@ -154,6 +154,11 @@ export function AlertFeed({ }); }, [facetFiltered]); + // Reset navigator selection when region or category filter changes. + useEffect(() => { + setActiveNavigatorGroupKey(null); + }, [regionFilter, categoryFilter]); + useEffect(() => { if (navigatorGroups.length === 0) { setActiveNavigatorGroupKey(null); From 4f927bb53e63418e67bd8d185864509597cab09e Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 21:10:27 +0100 Subject: [PATCH 29/58] fix Interpol notice links and map placement Replace API JSON URLs (ws-public.interpol.int/notices/v1/red/...) with human-readable web URLs (interpol.int/.../View-Red-Notices#ID). Override lat/lng from Interpol HQ (Lyon) to the person's nationality country centroid so notices pin to the correct location on the map. --- internal/collector/normalize/geocode.go | 11 +++++++++++ internal/collector/normalize/normalize.go | 5 +++++ internal/collector/run/run.go | 22 ++++++++++++++++------ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/internal/collector/normalize/geocode.go b/internal/collector/normalize/geocode.go index 7120144..bac1330 100644 --- a/internal/collector/normalize/geocode.go +++ b/internal/collector/normalize/geocode.go @@ -354,6 +354,17 @@ func init() { } } +// geocodeCountryCode returns the centroid for a 2-letter country code. +func geocodeCountryCode(code string) (lat, lng float64, name string, ok bool) { + code = strings.ToUpper(strings.TrimSpace(code)) + for i := range geoCountries { + if geoCountries[i].Code == code { + return geoCountries[i].Lat, geoCountries[i].Lng, geoCountries[i].Name, true + } + } + return 0, 0, "", false +} + // geocodeText scans text for country/region mentions and returns the // centroid of the best match. Prefers the rightmost mention in the text // (headlines typically put the subject location last, e.g. "Israeli diff --git a/internal/collector/normalize/normalize.go b/internal/collector/normalize/normalize.go index 89e1b75..e1f27de 100644 --- a/internal/collector/normalize/normalize.go +++ b/internal/collector/normalize/normalize.go @@ -219,6 +219,11 @@ func InterpolAlert(ctx Context, meta model.RegistrySource, noticeID string, titl if name := countryNameFromCode(code); name != "" { alert.Source.Country = name } + // Override lat/lng to the person's nationality country instead of + // Interpol HQ (Lyon, France). + if gLat, gLng, _, ok := geocodeCountryCode(code); ok { + alert.Lat, alert.Lng = jitter(gLat, gLng, meta.Source.SourceID+":"+link) + } } alert.Triage = score(ctx.Config, alert, FeedContext{ Summary: summary, diff --git a/internal/collector/run/run.go b/internal/collector/run/run.go index 6176699..7f0ef5a 100644 --- a/internal/collector/run/run.go +++ b/internal/collector/run/run.go @@ -414,12 +414,7 @@ func parseInterpolNotices(nctx normalize.Context, source model.RegistrySource, b if label != "" { title = titlePrefix + ": " + label } - link := notice.Links.Self.Href - if strings.TrimSpace(link) != "" { - if _, err := url.Parse(link); err == nil && !strings.HasPrefix(link, "http") { - link = (&url.URL{Scheme: "https", Host: "ws-public.interpol.int", Path: link}).String() - } - } + link := interpolWebURL(source.Type, notice.EntityID, notice.Links.Self.Href) countryCode := "" if len(notice.Nationalities) > 0 { countryCode = notice.Nationalities[0] @@ -485,6 +480,21 @@ func extractInterpolNoticeID(entityID string, link string) string { return strings.TrimSpace(parts[len(parts)-1]) } +// interpolWebURL converts an Interpol API self-link into a human-readable +// web URL. e.g. ".../notices/v1/red/2025-81216" becomes +// "https://www.interpol.int/How-we-work/Notices/Red-Notices/View-Red-Notices#2025-81216". +func interpolWebURL(sourceType string, entityID string, selfHref string) string { + noticeID := extractInterpolNoticeID(entityID, selfHref) + base := "https://www.interpol.int/How-we-work/Notices/Red-Notices/View-Red-Notices" + if sourceType == "interpol-yellow-json" { + base = "https://www.interpol.int/How-we-work/Notices/Yellow-Notices/View-Yellow-Notices" + } + if noticeID != "" { + return base + "#" + noticeID + } + return base +} + func (r Runner) fetchFBIWanted(ctx context.Context, fetcher fetch.Fetcher, nctx normalize.Context, source model.RegistrySource) ([]model.Alert, error) { limit := perSourceLimit(nctx.Config, source) pageSize := 40 From 3fb9b224326daf58272fd4f827949b4430368901 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 21:28:35 +0100 Subject: [PATCH 30/58] feat: incremental Interpol notice accumulation with cursor-based pagination MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Interpol has ~6.4k red and ~4k yellow notices. Instead of fetching all at once, each run fetches a 320-notice window (2 pages × 160) and advances a persistent cursor. State reconciliation carries forward previously accumulated alerts for sources marked accumulate:true, building the full corpus over successive runs. --- internal/collector/config/config.go | 3 + internal/collector/model/source.go | 1 + internal/collector/run/run.go | 85 ++++++++++++++++++-------- internal/collector/state/state.go | 34 ++++++++++- internal/collector/state/state_test.go | 37 ++++++++++- registry/source_registry.json | 10 +-- 6 files changed, 139 insertions(+), 31 deletions(-) diff --git a/internal/collector/config/config.go b/internal/collector/config/config.go index 7243dca..a1a1441 100644 --- a/internal/collector/config/config.go +++ b/internal/collector/config/config.go @@ -73,6 +73,7 @@ type Config struct { SourceDBMergeRegistry bool SourceDBExportRegistry bool CuratedSeedPath string + CursorsPath string APIEnabled bool APIAddr string } @@ -127,6 +128,7 @@ func Default() Config { SourceDBMergeRegistry: false, SourceDBExportRegistry: false, CuratedSeedPath: "registry/curated_agencies.seed.json", + CursorsPath: "public/cursors.json", APIEnabled: false, APIAddr: ":3001", } @@ -183,6 +185,7 @@ func FromEnv() Config { cfg.SourceDBMergeRegistry = envBool("SOURCE_DB_MERGE_REGISTRY", cfg.SourceDBMergeRegistry) cfg.SourceDBExportRegistry = envBool("SOURCE_DB_EXPORT_REGISTRY", cfg.SourceDBExportRegistry) cfg.CuratedSeedPath = envString("CURATED_SEED_PATH", cfg.CuratedSeedPath) + cfg.CursorsPath = envString("CURSORS_PATH", cfg.CursorsPath) cfg.APIEnabled = envBool("API_ENABLED", cfg.APIEnabled) cfg.APIAddr = envString("API_ADDR", cfg.APIAddr) return cfg diff --git a/internal/collector/model/source.go b/internal/collector/model/source.go index d1ee7bd..ee8e079 100644 --- a/internal/collector/model/source.go +++ b/internal/collector/model/source.go @@ -16,6 +16,7 @@ type RegistrySource struct { Lat float64 `json:"lat"` Lng float64 `json:"lng"` MaxItems int `json:"max_items"` + Accumulate bool `json:"accumulate,omitempty"` IncludeKeywords []string `json:"include_keywords,omitempty"` ExcludeKeywords []string `json:"exclude_keywords,omitempty"` SourceQuality float64 `json:"source_quality,omitempty"` diff --git a/internal/collector/run/run.go b/internal/collector/run/run.go index 7f0ef5a..0919653 100644 --- a/internal/collector/run/run.go +++ b/internal/collector/run/run.go @@ -97,12 +97,14 @@ func (r Runner) runOnce(ctx context.Context, cfg config.Config) error { fmt.Fprintf(r.stderr, "WARN category dictionary load failed (falling back to legacy filters): %v\n", err) } + cursors := state.ReadCursors(cfg.CursorsPath) + alerts := []model.Alert{normalize.StaticInterpolEntry(now)} sourceHealth := make([]model.SourceHealthEntry, 0, len(sources)) for _, source := range sources { startedAt := time.Now().UTC() fetcher := fetch.FetcherFor(source.FetchMode, client, browser) - batch, err := r.fetchSource(ctx, fetcher, browser, nctx, source, categoryDictionary) + batch, err := r.fetchSource(ctx, fetcher, browser, nctx, source, categoryDictionary, cursors) // Retry once for transient errors (timeout, EOF) after a short backoff. if err != nil { @@ -115,7 +117,7 @@ func (r Runner) runOnce(ctx context.Context, cfg config.Config) error { case <-ctx.Done(): } if ctx.Err() == nil { - batch, err = r.fetchSource(ctx, fetcher, browser, nctx, source, categoryDictionary) + batch, err = r.fetchSource(ctx, fetcher, browser, nctx, source, categoryDictionary, cursors) } } } @@ -142,6 +144,10 @@ func (r Runner) runOnce(ctx context.Context, cfg config.Config) error { alerts = append(alerts, batch...) } + if err := state.WriteCursors(cfg.CursorsPath, cursors); err != nil { + fmt.Fprintf(r.stderr, "WARN failed to save cursors: %v\n", err) + } + deduped, duplicateAudit := normalize.Deduplicate(alerts) active, filtered := normalize.FilterActive(cfg, deduped) populateSourceHealth(sourceHealth, active, filtered) @@ -153,7 +159,13 @@ func (r Runner) runOnce(ctx context.Context, cfg config.Config) error { if err != nil { return err } - currentActive, currentFiltered, fullState := state.Reconcile(cfg, active, filtered, previous, now) + accumulateSources := map[string]bool{} + for _, s := range sources { + if s.Accumulate { + accumulateSources[s.Source.SourceID] = true + } + } + currentActive, currentFiltered, fullState := state.Reconcile(cfg, active, filtered, previous, now, accumulateSources) replacementQueue := buildReplacementQueue(sourceHealth, sources) if err := deactivateReplacementSources(ctx, cfg.RegistryPath, replacementQueue); err != nil { return err @@ -168,7 +180,7 @@ func (r Runner) runOnce(ctx context.Context, cfg config.Config) error { return err } -func (r Runner) fetchSource(ctx context.Context, fetcher fetch.Fetcher, browser *fetch.BrowserClient, nctx normalize.Context, source model.RegistrySource, categoryDictionary *dictionary.Store) ([]model.Alert, error) { +func (r Runner) fetchSource(ctx context.Context, fetcher fetch.Fetcher, browser *fetch.BrowserClient, nctx normalize.Context, source model.RegistrySource, categoryDictionary *dictionary.Store, cursors state.Cursors) ([]model.Alert, error) { switch source.Type { case "rss": return r.fetchRSS(ctx, fetcher, nctx, source) @@ -177,7 +189,7 @@ func (r Runner) fetchSource(ctx context.Context, fetcher fetch.Fetcher, browser case "kev-json": return r.fetchKEV(ctx, fetcher, nctx, source) case "interpol-red-json", "interpol-yellow-json": - return r.fetchInterpol(ctx, fetcher, browser, nctx, source) + return r.fetchInterpol(ctx, fetcher, browser, nctx, source, cursors) case "fbi-wanted-json": return r.fetchFBIWanted(ctx, fetcher, nctx, source) case "travelwarning-json": @@ -309,10 +321,11 @@ func (r Runner) fetchKEV(ctx context.Context, fetcher fetch.Fetcher, nctx normal return out, nil } -func (r Runner) fetchInterpol(ctx context.Context, fetcher fetch.Fetcher, browser *fetch.BrowserClient, nctx normalize.Context, source model.RegistrySource) ([]model.Alert, error) { +func (r Runner) fetchInterpol(ctx context.Context, fetcher fetch.Fetcher, browser *fetch.BrowserClient, nctx normalize.Context, source model.RegistrySource, cursors state.Cursors) ([]model.Alert, error) { limit := perSourceLimit(nctx.Config, source) - pageSize := 20 + pageSize := 160 var allNotices []model.Alert + sid := source.Source.SourceID // Interpol's API sits behind Akamai WAF and requires XHR-style headers // with Referer/Origin pointing to the Interpol website. @@ -325,10 +338,9 @@ func (r Runner) fetchInterpol(ctx context.Context, fetcher fetch.Fetcher, browse "X-Requested-With": "XMLHttpRequest", } - // Use TextWithHeaders if the fetcher is a *Client (stealth HTTP). clientFetcher, isClient := fetcher.(*fetch.Client) - for page := 1; len(allNotices) < limit; page++ { + fetchPage := func(page int) ([]model.Alert, error) { pageURL := buildInterpolPageURL(source.FeedURL, page, pageSize) var body []byte var err error @@ -338,31 +350,54 @@ func (r Runner) fetchInterpol(ctx context.Context, fetcher fetch.Fetcher, browse body, err = fetcher.Text(ctx, pageURL, source.FollowRedirects, "application/json") } if err != nil { - // If first page fails, try browser fallback for the whole batch. - if page == 1 && browser != nil { - fmt.Fprintf(r.stderr, "WARN %s: stealth fetch failed, trying browser fallback: %v\n", source.Source.AuthorityName, err) - bBody, bErr := fetchInterpolViaBrowser(ctx, browser, source) - if bErr == nil && len(bBody) > 0 { - return parseInterpolNotices(nctx, source, bBody) - } + return nil, err + } + return parseInterpolNotices(nctx, source, body) + } + + // Always fetch page 1 first to pick up new notices. + batch, err := fetchPage(1) + if err != nil { + if browser != nil { + fmt.Fprintf(r.stderr, "WARN %s: stealth fetch failed, trying browser fallback: %v\n", source.Source.AuthorityName, err) + bBody, bErr := fetchInterpolViaBrowser(ctx, browser, source) + if bErr == nil && len(bBody) > 0 { + return parseInterpolNotices(nctx, source, bBody) } - break } - batch, err := parseInterpolNotices(nctx, source, body) + return nil, err + } + allNotices = append(allNotices, batch...) + lastPageFetched := 1 + + // Resume from cursor to backfill older pages. + resumePage := cursors[sid] + if resumePage < 2 { + resumePage = 2 + } + for page := resumePage; len(allNotices) < limit; page++ { + select { + case <-time.After(1 * time.Second): + case <-ctx.Done(): + cursors[sid] = page + return allNotices, nil + } + batch, err := fetchPage(page) if err != nil { break } allNotices = append(allNotices, batch...) + lastPageFetched = page if len(batch) < pageSize { - break // last page - } - // Polite delay between page requests. - select { - case <-time.After(2 * time.Second): - case <-ctx.Done(): - return allNotices, nil + // Reached the end — wrap cursor back to 2 for next run. + lastPageFetched = 1 + break } } + + // Advance cursor for next run. + cursors[sid] = lastPageFetched + 1 + if len(allNotices) > limit { allNotices = allNotices[:limit] } diff --git a/internal/collector/state/state.go b/internal/collector/state/state.go index 80682d8..0388920 100644 --- a/internal/collector/state/state.go +++ b/internal/collector/state/state.go @@ -25,7 +25,33 @@ func Read(path string) []model.Alert { return alerts } -func Reconcile(cfg config.Config, active []model.Alert, filtered []model.Alert, previous []model.Alert, now time.Time) ([]model.Alert, []model.Alert, []model.Alert) { +// Cursors tracks the resume page for paginated sources that accumulate. +type Cursors map[string]int // sourceID → next page to fetch + +func ReadCursors(path string) Cursors { + data, err := os.ReadFile(path) + if err != nil { + return Cursors{} + } + var c Cursors + if err := json.Unmarshal(data, &c); err != nil { + return Cursors{} + } + return c +} + +func WriteCursors(path string, c Cursors) error { + data, err := json.MarshalIndent(c, "", " ") + if err != nil { + return err + } + return os.WriteFile(path, data, 0644) +} + +// Reconcile merges current fetch results with previous state. +// accumulateSources lists source IDs where alerts carry forward across runs +// (paginated APIs like Interpol where each run only fetches a window). +func Reconcile(cfg config.Config, active []model.Alert, filtered []model.Alert, previous []model.Alert, now time.Time, accumulateSources map[string]bool) ([]model.Alert, []model.Alert, []model.Alert) { nowISO := now.UTC().Format(time.RFC3339) retentionCutoff := now.Add(-time.Duration(cfg.RemovedRetentionDays) * 24 * time.Hour) previousByID := map[string]model.Alert{} @@ -62,6 +88,12 @@ func Reconcile(cfg config.Config, active []model.Alert, filtered []model.Alert, if _, ok := presentByID[prev.AlertID]; ok { continue } + // Accumulating sources: carry forward active alerts not in this batch. + if accumulateSources[prev.SourceID] && prev.Status == "active" { + currentActive = append(currentActive, prev) + presentByID[prev.AlertID] = struct{}{} + continue + } if prev.Status == "removed" { lastSeen, err := time.Parse(time.RFC3339, prev.LastSeen) if err == nil && !lastSeen.Before(retentionCutoff) { diff --git a/internal/collector/state/state_test.go b/internal/collector/state/state_test.go index ffe5119..60ddc0a 100644 --- a/internal/collector/state/state_test.go +++ b/internal/collector/state/state_test.go @@ -21,7 +21,7 @@ func TestReconcileCarriesForwardAndRemoves(t *testing.T) { {AlertID: "c", FirstSeen: now.Add(-24 * time.Hour).Format(time.RFC3339), Status: "active", LastSeen: now.Add(-time.Hour).Format(time.RFC3339)}, } - currentActive, currentFiltered, fullState := Reconcile(cfg, active, filtered, previous, now) + currentActive, currentFiltered, fullState := Reconcile(cfg, active, filtered, previous, now, nil) if currentActive[0].FirstSeen != previous[0].FirstSeen { t.Fatalf("expected first_seen to carry forward, got %q", currentActive[0].FirstSeen) } @@ -38,3 +38,38 @@ func TestReconcileCarriesForwardAndRemoves(t *testing.T) { t.Fatalf("expected removed alert in state %#v", fullState) } } + +func TestReconcileAccumulateCarriesForward(t *testing.T) { + cfg := config.Default() + now := time.Date(2026, 1, 2, 3, 4, 5, 0, time.UTC) + // This run only fetches alert "a" (new page). + active := []model.Alert{{AlertID: "a", SourceID: "interpol-red"}} + // Previous state has "b" from an earlier run — should carry forward. + previous := []model.Alert{ + {AlertID: "b", SourceID: "interpol-red", Status: "active", FirstSeen: "2026-01-01T00:00:00Z", LastSeen: "2026-01-01T12:00:00Z"}, + {AlertID: "c", SourceID: "other-source", Status: "active", FirstSeen: "2026-01-01T00:00:00Z", LastSeen: "2026-01-01T12:00:00Z"}, + } + acc := map[string]bool{"interpol-red": true} + + currentActive, _, fullState := Reconcile(cfg, active, nil, previous, now, acc) + + foundB := false + for _, a := range currentActive { + if a.AlertID == "b" { + foundB = true + } + } + if !foundB { + t.Fatalf("expected accumulated alert 'b' in currentActive, got %v", currentActive) + } + + foundCRemoved := false + for _, a := range fullState { + if a.AlertID == "c" && a.Status == "removed" { + foundCRemoved = true + } + } + if !foundCRemoved { + t.Fatalf("expected non-accumulating alert 'c' to be removed in fullState") + } +} diff --git a/registry/source_registry.json b/registry/source_registry.json index 099c280..1d0cd8a 100644 --- a/registry/source_registry.json +++ b/registry/source_registry.json @@ -2848,12 +2848,13 @@ "authority_type": "police", "base_url": "https://ws-public.interpol.int" }, - "feed_url": "https://ws-public.interpol.int/notices/v1/red?resultPerPage=20&page=1", + "feed_url": "https://ws-public.interpol.int/notices/v1/red?resultPerPage=160&page=1", + "accumulate": true, "category": "wanted_suspect", "region_tag": "INT", "lat": 48.86, "lng": 2.35, - "max_items": 200 + "max_items": 320 }, { "type": "interpol-yellow-json", @@ -2866,12 +2867,13 @@ "authority_type": "police", "base_url": "https://ws-public.interpol.int" }, - "feed_url": "https://ws-public.interpol.int/notices/v1/yellow?resultPerPage=20&page=1", + "feed_url": "https://ws-public.interpol.int/notices/v1/yellow?resultPerPage=160&page=1", + "accumulate": true, "category": "missing_person", "region_tag": "INT", "lat": 48.86, "lng": 2.35, - "max_items": 200 + "max_items": 320 }, { "type": "rss", From 1078a48de9b544e733101f7ede98ed8b119df389 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 21:33:21 +0100 Subject: [PATCH 31/58] fix: constrain map bounds to prevent duplicate earth views Add maxBounds, maxBoundsViscosity, minZoom and noWrap to stop vertical scrolling past the world edge and tile repetition. --- src/components/GlobeView.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/GlobeView.tsx b/src/components/GlobeView.tsx index 72296e8..a50f32b 100644 --- a/src/components/GlobeView.tsx +++ b/src/components/GlobeView.tsx @@ -90,13 +90,16 @@ export function GlobeView({ const map = L.map(containerRef.current, { center: vp.center, zoom: vp.zoom, + minZoom: 2, + maxBounds: L.latLngBounds([-85, -180], [85, 180]), + maxBoundsViscosity: 1.0, zoomControl: false, attributionControl: false, }); L.tileLayer( "https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png", - { maxZoom: 18, subdomains: "abcd" }, + { maxZoom: 18, subdomains: "abcd", noWrap: true }, ).addTo(map); L.control.zoom({ position: "bottomright" }).addTo(map); From 39abf9745c080626b9af874b3892818514c95e59 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 22:53:58 +0100 Subject: [PATCH 32/58] fix: bump map min zoom to fill container, add German severity keywords Increase global/international zoom and minZoom from 2 to 3 to eliminate white gaps at map edges. Add German-language keywords to severity inference so CERT.AT/BSI advisories get correct severity levels. --- internal/collector/normalize/normalize.go | 8 ++++---- src/components/GlobeView.tsx | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/internal/collector/normalize/normalize.go b/internal/collector/normalize/normalize.go index e1f27de..86cdd34 100644 --- a/internal/collector/normalize/normalize.go +++ b/internal/collector/normalize/normalize.go @@ -530,13 +530,13 @@ func defaultSeverity(category string) string { func inferSeverity(title string, fallback string) string { t := strings.ToLower(title) switch { - case containsAny(t, "critical", "emergency", "zero-day", "0-day", "ransomware", "actively exploited", "exploitation", "breach", "data leak", "crypto heist", "million stolen", "wanted", "fugitive", "murder", "homicide", "missing", "amber alert", "kidnap", "do not travel"): + case containsAny(t, "critical", "kritische", "emergency", "zero-day", "0-day", "ransomware", "actively exploited", "exploitation", "breach", "data leak", "crypto heist", "million stolen", "wanted", "fugitive", "murder", "homicide", "missing", "amber alert", "kidnap", "do not travel", "notfall"): return "critical" - case containsAny(t, "hack", "compromise", "vulnerability", "high", "severe", "urgent", "fatal", "death", "shooting", "fraud", "scam", "phishing", "reconsider travel", "avoid non-essential travel"): + case containsAny(t, "hack", "compromise", "vulnerability", "schwachstelle", "sicherheitslücke", "high", "severe", "urgent", "dringend", "fatal", "death", "shooting", "fraud", "scam", "phishing", "reconsider travel", "avoid non-essential travel", "warnung", "gefährlich"): return "high" - case containsAny(t, "arrested", "charged", "sentenced", "medium", "moderate"): + case containsAny(t, "arrested", "charged", "sentenced", "medium", "moderate", "festgenommen", "verurteilt"): return "medium" - case containsAny(t, "low", "informational"): + case containsAny(t, "low", "informational", "infopaket", "infoblatt", "handreichung", "leitfaden", "newsletter"): return "info" default: return fallback diff --git a/src/components/GlobeView.tsx b/src/components/GlobeView.tsx index a50f32b..9e69458 100644 --- a/src/components/GlobeView.tsx +++ b/src/components/GlobeView.tsx @@ -25,8 +25,8 @@ const REGION_VIEWPORTS: Record = { Asia: { center: [34, 100], zoom: 3 }, Oceania: { center: [-28, 140], zoom: 4 }, Caribbean: { center: [18, -75], zoom: 5 }, - International: { center: [20, 0], zoom: 2 }, - all: { center: [20, 0], zoom: 2 }, + International: { center: [20, 0], zoom: 3 }, + all: { center: [20, 0], zoom: 3 }, }; /* ── Props ────────────────────────────────────────────────────────── */ @@ -90,7 +90,7 @@ export function GlobeView({ const map = L.map(containerRef.current, { center: vp.center, zoom: vp.zoom, - minZoom: 2, + minZoom: 3, maxBounds: L.latLngBounds([-85, -180], [85, 180]), maxBoundsViscosity: 1.0, zoomControl: false, From 2cf400c698c794d79446c7451be54315fe292fd5 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 22:56:05 +0100 Subject: [PATCH 33/58] docs: add user guide, cap Interpol notices at 160 per type Document that EUOSINT intentionally pulls only the newest 160 red and 160 yellow Interpol notices per run to avoid data overflow. Also covers severity classification, map tiles, and collector cycle behavior. --- docs/userguide.md | 41 +++++++++++++++++++++++++++++++++++ registry/source_registry.json | 6 ++--- 2 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 docs/userguide.md diff --git a/docs/userguide.md b/docs/userguide.md new file mode 100644 index 0000000..87a698c --- /dev/null +++ b/docs/userguide.md @@ -0,0 +1,41 @@ +# EUOSINT User Guide + +## Data Sources + +### Interpol Notices + +EUOSINT pulls the **newest 160 Red Notices** (wanted suspects) and **newest 160 Yellow Notices** (missing persons) from the Interpol public API per collector run. This limit is intentional to avoid data overflow and excessive API load. + +- Red Notices: ~6,400 active notices globally +- Yellow Notices: ~4,000 active notices globally + +Only the most recent window is fetched each cycle. Notices are pinned on the map to the suspect's nationality country rather than Interpol HQ in Lyon. + +### Severity Classification + +Alerts are classified into five severity levels based on title keyword analysis: + +| Level | Examples | +|-------|---------| +| **Critical** | Zero-day exploits, ransomware, active exploitation, wanted fugitives, missing persons, AMBER alerts | +| **High** | Vulnerabilities, compromises, phishing campaigns, fraud, urgent advisories | +| **Medium** | Arrests, charges, sentences, moderate-severity advisories | +| **Info** | Newsletters, info packets (Infopaket), guidance documents (Handreichung, Leitfaden) | + +Keyword matching supports both English and German terms (e.g., "Kritische Schwachstelle" maps to critical/high). + +### Map Tiles + +The map uses [CARTO](https://carto.com/) dark basemap tiles loaded from their CDN. An active internet connection is required for map rendering. Missing or slow-loading tiles indicate network connectivity issues to `basemaps.cartocdn.com`. + +### Collector Cycle + +The collector runs on a configurable interval (default: 15 minutes). Each run: + +1. Fetches all active sources from the registry +2. Parses and normalizes alerts +3. Deduplicates across sources +4. Reconciles with previous state (tracks new, active, and removed alerts) +5. Outputs JSON snapshots consumed by the frontend + +Removed alerts (e.g., a resolved Interpol notice) are retained in state for 14 days before being purged. diff --git a/registry/source_registry.json b/registry/source_registry.json index 1d0cd8a..b78d636 100644 --- a/registry/source_registry.json +++ b/registry/source_registry.json @@ -2849,12 +2849,11 @@ "base_url": "https://ws-public.interpol.int" }, "feed_url": "https://ws-public.interpol.int/notices/v1/red?resultPerPage=160&page=1", - "accumulate": true, "category": "wanted_suspect", "region_tag": "INT", "lat": 48.86, "lng": 2.35, - "max_items": 320 + "max_items": 160 }, { "type": "interpol-yellow-json", @@ -2868,12 +2867,11 @@ "base_url": "https://ws-public.interpol.int" }, "feed_url": "https://ws-public.interpol.int/notices/v1/yellow?resultPerPage=160&page=1", - "accumulate": true, "category": "missing_person", "region_tag": "INT", "lat": 48.86, "lng": 2.35, - "max_items": 320 + "max_items": 160 }, { "type": "rss", From 3ca2ba5c70dca2e91d3f3ed0b9f3a9bbc97feda4 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 22:58:10 +0100 Subject: [PATCH 34/58] docs: comprehensive user guide with all alert categories and regions Cover all 17 alert categories with descriptions and example sources, severity classification rules, Interpol notice limits, map tiles, collector cycle, and region scoping. --- docs/userguide.md | 144 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 126 insertions(+), 18 deletions(-) diff --git a/docs/userguide.md b/docs/userguide.md index 87a698c..4cc6433 100644 --- a/docs/userguide.md +++ b/docs/userguide.md @@ -1,41 +1,149 @@ # EUOSINT User Guide -## Data Sources +## Alert Categories -### Interpol Notices +EUOSINT classifies every alert into one of the following categories. Each category groups a specific type of intelligence and is sourced from relevant official feeds. + +### Cyber Advisory +Vulnerability disclosures, patch advisories, and threat intelligence from national CERTs and cybersecurity agencies. Covers zero-days, actively exploited CVEs, ransomware campaigns, and critical infrastructure advisories. + +**Sources:** CISA, BSI, CERT-EU, CERT.AT, NCSC-UK, ANSSI, ENISA, NVD/KEV, and 60+ national CERTs worldwide. + +### Wanted Suspect +Active arrest warrants and wanted person notices from law enforcement agencies. Includes fugitives, persons of interest, and internationally wanted individuals. + +**Sources:** Interpol Red Notices (newest 160 per run), FBI Most Wanted, Europol Most Wanted, BKA, national police agencies across Europe, Americas, and Asia-Pacific. + +### Missing Person +Active missing person cases including children, endangered adults, and unidentified remains. Covers AMBER alerts and international missing person notices. + +**Sources:** Interpol Yellow Notices (newest 160 per run), NCMEC, NamUs, BKA Vermisste, national police missing person feeds. + +### Public Appeal +Police appeals for information from the public — witness calls, identification requests, crime tip lines, and community safety notices. + +**Sources:** Metropolitan Police, Police.uk, Polizei.de state feeds, Gendarmerie, FBI tips, and regional law enforcement across 30+ countries. + +### Fraud Alert +Consumer fraud warnings, financial crime alerts, scam advisories, and money laundering notices from financial regulators and law enforcement. + +**Sources:** FCA, BaFin, SEC, FINMA, Europol financial crime, ACCC Scamwatch, national consumer protection agencies. + +### Intelligence Report +Strategic intelligence assessments, geopolitical analysis, and security briefings from think tanks and intelligence-adjacent organisations. + +**Sources:** SIPRI, IISS, RUSI, Jane's, UN Security Council press, OSCE, NATO CCDCOE, national intelligence agency public releases. + +### Travel Warning +Government-issued travel advisories and consular warnings. Covers security situations, health risks, and entry restrictions for countries and regions. + +**Sources:** US State Department, UK FCDO, German Auswaertiges Amt, and other foreign ministry travel advisory feeds. + +### Conflict Monitoring +Armed conflict tracking, ceasefire violations, military operations, and peace process updates from conflict zones worldwide. + +**Sources:** UN Peace & Security, SIPRI conflict data, OSCE monitoring missions, peacekeeping operation feeds. + +### Humanitarian Security +Security incidents affecting humanitarian operations — aid worker safety, access restrictions, and operational environment assessments in crisis zones. + +**Sources:** ICRC field operations, ICRC IHL updates, UN OCHA, UNHCR, and humanitarian coordination feeds. + +### Humanitarian Tasking +Active humanitarian missions, disaster response deployments, and relief operation updates. + +**Sources:** UN Peacekeeping (Blue Helmets), UNOCHA coordination, UN humanitarian aid operations. + +### Health Emergency +Disease outbreaks, pandemic updates, public health emergencies, and biosecurity alerts from health authorities. + +**Sources:** WHO, ECDC, CDC, RKI, national public health agencies. + +### Public Safety +Civil protection alerts, natural disaster warnings, critical infrastructure incidents, and emergency notifications. + +**Sources:** National emergency management agencies, civil protection feeds, disaster response organisations. + +### Emergency Management +Large-scale emergency coordination, disaster declarations, evacuation orders, and crisis management updates. + +**Sources:** FEMA, BBK (German Federal Office of Civil Protection), EU Civil Protection Mechanism. + +### Terrorism Tip +Counter-terrorism alerts, threat assessments, and public safety notices related to terrorism and extremism. + +**Sources:** Europol TE-SAT, national counter-terrorism units, security service public advisories. + +### Private Sector +Corporate security alerts, supply chain disruptions, and industry-specific threat intelligence relevant to private sector operations. + +**Sources:** Industry ISACs, sector-specific CERTs, corporate security advisory feeds. + +--- + +## Severity Levels + +Every alert is assigned a severity level based on keyword analysis of the title and content: + +| Level | Colour | Criteria | +|-------|--------|----------| +| **Critical** | Red | Zero-days, ransomware, active exploitation, wanted fugitives, missing persons, AMBER alerts, emergencies | +| **High** | Orange | Vulnerabilities, compromises, phishing, fraud, urgent advisories, security warnings | +| **Medium** | Yellow | Arrests, charges, sentences, moderate-severity items | +| **Low** | Blue | Minor advisories, routine updates | +| **Informational** | Grey | Newsletters, info packets, guidance documents, educational material | + +Keyword matching supports English and German (e.g., "Kritische Schwachstelle" = critical, "Sicherheitslücke" = high, "Infopaket" = informational). + +--- + +## Interpol Notices EUOSINT pulls the **newest 160 Red Notices** (wanted suspects) and **newest 160 Yellow Notices** (missing persons) from the Interpol public API per collector run. This limit is intentional to avoid data overflow and excessive API load. - Red Notices: ~6,400 active notices globally - Yellow Notices: ~4,000 active notices globally -Only the most recent window is fetched each cycle. Notices are pinned on the map to the suspect's nationality country rather than Interpol HQ in Lyon. +Only the most recent window is fetched each cycle. Notices are pinned on the map to the suspect's nationality country rather than Interpol HQ in Lyon. Links point to the Interpol web view, not the raw API. -### Severity Classification +--- -Alerts are classified into five severity levels based on title keyword analysis: +## Map -| Level | Examples | -|-------|---------| -| **Critical** | Zero-day exploits, ransomware, active exploitation, wanted fugitives, missing persons, AMBER alerts | -| **High** | Vulnerabilities, compromises, phishing campaigns, fraud, urgent advisories | -| **Medium** | Arrests, charges, sentences, moderate-severity advisories | -| **Info** | Newsletters, info packets (Infopaket), guidance documents (Handreichung, Leitfaden) | - -Keyword matching supports both English and German terms (e.g., "Kritische Schwachstelle" maps to critical/high). +The map uses [CARTO](https://carto.com/) dark basemap tiles loaded from their CDN. An active internet connection is required for map rendering. Missing or slow-loading tiles indicate network connectivity issues to `basemaps.cartocdn.com`. -### Map Tiles +Alerts are plotted at their source country coordinates. International sources (Interpol, UN agencies) are geocoded to the relevant crisis or nationality country when possible. -The map uses [CARTO](https://carto.com/) dark basemap tiles loaded from their CDN. An active internet connection is required for map rendering. Missing or slow-loading tiles indicate network connectivity issues to `basemaps.cartocdn.com`. +--- -### Collector Cycle +## Collector Cycle The collector runs on a configurable interval (default: 15 minutes). Each run: -1. Fetches all active sources from the registry -2. Parses and normalizes alerts +1. Fetches all active sources from the registry (~266 sources) +2. Parses and normalizes alerts with severity and category classification 3. Deduplicates across sources 4. Reconciles with previous state (tracks new, active, and removed alerts) 5. Outputs JSON snapshots consumed by the frontend Removed alerts (e.g., a resolved Interpol notice) are retained in state for 14 days before being purged. + +--- + +## Regions + +The dashboard supports region-scoped views: + +| Region | Coverage | +|--------|----------| +| **Global** | All sources worldwide | +| **Europe** | EU/EEA member states, UK, Switzerland, Balkans, Eastern Europe | +| **North America** | US, Canada, Mexico | +| **South America** | Central and South America | +| **Asia** | East Asia, Southeast Asia, South Asia, Central Asia, Middle East | +| **Africa** | All African nations | +| **Oceania** | Australia, New Zealand, Pacific Islands | +| **Caribbean** | Caribbean island nations | +| **International** | Sources with global scope (Interpol, UN, ICRC) | + +Region shortcuts in the header bar and the dropdown selector both filter the map and alert feed simultaneously. From 67b3b0148ec0c7af78d05ce74591ffd1de0fed54 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 23:13:26 +0100 Subject: [PATCH 35/58] feat: add environmental disaster and disease outbreak categories Add 12 new sources: GDACS disasters, USGS earthquakes, NOAA oil/chem incidents, Smithsonian volcanoes, EMSA maritime, IAEA nuclear, WHO, ECDC epidemiological updates + risk assessments, CDC, WOAH zoonotic. Reject ECB press releases (general news, not fraud intel). Add severity keywords for outbreaks, natural disasters, and hazmat. Fraud sources will appear after next dev-restart (DB merge on startup). --- internal/collector/normalize/normalize.go | 8 +- registry/source_registry.json | 192 ++++++++++++++++++++++ src/index.css | 2 + src/lib/severity.ts | 8 + src/types/alert.ts | 4 +- 5 files changed, 211 insertions(+), 3 deletions(-) diff --git a/internal/collector/normalize/normalize.go b/internal/collector/normalize/normalize.go index 86cdd34..45d8933 100644 --- a/internal/collector/normalize/normalize.go +++ b/internal/collector/normalize/normalize.go @@ -522,6 +522,10 @@ func defaultSeverity(category string) string { return "high" case "travel_warning": return "high" + case "environmental_disaster", "disease_outbreak": + return "high" + case "emergency_management", "health_emergency": + return "high" default: return "medium" } @@ -530,9 +534,9 @@ func defaultSeverity(category string) string { func inferSeverity(title string, fallback string) string { t := strings.ToLower(title) switch { - case containsAny(t, "critical", "kritische", "emergency", "zero-day", "0-day", "ransomware", "actively exploited", "exploitation", "breach", "data leak", "crypto heist", "million stolen", "wanted", "fugitive", "murder", "homicide", "missing", "amber alert", "kidnap", "do not travel", "notfall"): + case containsAny(t, "critical", "kritische", "emergency", "zero-day", "0-day", "ransomware", "actively exploited", "exploitation", "breach", "data leak", "crypto heist", "million stolen", "wanted", "fugitive", "murder", "homicide", "missing", "amber alert", "kidnap", "do not travel", "notfall", "pandemic", "ebola", "plague", "tsunami", "earthquake", "eruption", "nuclear incident", "radiation leak", "oil spill", "explosion"): return "critical" - case containsAny(t, "hack", "compromise", "vulnerability", "schwachstelle", "sicherheitslücke", "high", "severe", "urgent", "dringend", "fatal", "death", "shooting", "fraud", "scam", "phishing", "reconsider travel", "avoid non-essential travel", "warnung", "gefährlich"): + case containsAny(t, "hack", "compromise", "vulnerability", "schwachstelle", "sicherheitslücke", "high", "severe", "urgent", "dringend", "fatal", "death", "shooting", "fraud", "scam", "phishing", "reconsider travel", "avoid non-essential travel", "warnung", "gefährlich", "outbreak", "epidemic", "cholera", "mpox", "avian influenza", "flood", "wildfire", "cyclone", "hurricane", "typhoon", "drought", "chemical spill", "hazmat"): return "high" case containsAny(t, "arrested", "charged", "sentenced", "medium", "moderate", "festgenommen", "verurteilt"): return "medium" diff --git a/registry/source_registry.json b/registry/source_registry.json index b78d636..42f1bfc 100644 --- a/registry/source_registry.json +++ b/registry/source_registry.json @@ -5403,6 +5403,8 @@ }, { "type": "rss", + "promotion_status": "rejected", + "rejection_reason": "General press releases, not fraud intelligence", "source": { "source_id": "ecb-press", "authority_name": "ECB Press Releases", @@ -5621,5 +5623,195 @@ "region_tag": "US", "lat": 39.29, "lng": -76.61 + }, + { + "type": "rss", + "source": { + "source_id": "gdacs-disasters", + "authority_name": "GDACS Global Disasters", + "country": "International", + "country_code": "INT", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://www.gdacs.org" + }, + "feed_url": "https://www.gdacs.org/xml/rss.xml", + "category": "environmental_disaster", + "region_tag": "INT", + "lat": 46.23, + "lng": 6.05, + "max_items": 50 + }, + { + "type": "rss", + "source": { + "source_id": "usgs-earthquakes", + "authority_name": "USGS Significant Earthquakes", + "country": "United States", + "country_code": "US", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://earthquake.usgs.gov" + }, + "feed_url": "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_week.atom", + "category": "environmental_disaster", + "region_tag": "INT", + "lat": 38.95, + "lng": -77.37, + "max_items": 40 + }, + { + "type": "rss", + "source": { + "source_id": "noaa-incidents", + "authority_name": "NOAA Incident News", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "public_safety_program", + "base_url": "https://incidentnews.noaa.gov" + }, + "feed_url": "https://incidentnews.noaa.gov/incidents.rss", + "category": "environmental_disaster", + "region_tag": "US", + "lat": 38.85, + "lng": -76.93 + }, + { + "type": "rss", + "source": { + "source_id": "smithsonian-volcanoes", + "authority_name": "Smithsonian Global Volcanism Program", + "country": "United States", + "country_code": "US", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://volcano.si.edu" + }, + "feed_url": "https://volcano.si.edu/news/WeeklyVolcanoRSS.xml", + "category": "environmental_disaster", + "region_tag": "INT", + "lat": 38.89, + "lng": -77.03 + }, + { + "type": "rss", + "source": { + "source_id": "emsa-maritime", + "authority_name": "EMSA Maritime Safety", + "country": "Portugal", + "country_code": "PT", + "region": "Europe", + "authority_type": "regulatory", + "base_url": "https://www.emsa.europa.eu" + }, + "feed_url": "https://www.emsa.europa.eu/newsroom/latest-news.feed?type=rss&format=feed", + "category": "environmental_disaster", + "region_tag": "EU", + "lat": 38.71, + "lng": -9.14 + }, + { + "type": "rss", + "source": { + "source_id": "iaea-news", + "authority_name": "IAEA Nuclear News", + "country": "Austria", + "country_code": "AT", + "region": "International", + "authority_type": "regulatory", + "base_url": "https://www.iaea.org" + }, + "feed_url": "https://www.iaea.org/feeds/news", + "category": "environmental_disaster", + "region_tag": "INT", + "lat": 48.23, + "lng": 16.41 + }, + { + "type": "rss", + "source": { + "source_id": "who-news", + "authority_name": "WHO Disease & Health News", + "country": "Switzerland", + "country_code": "CH", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://www.who.int" + }, + "feed_url": "https://www.who.int/rss-feeds/news-english.xml", + "category": "disease_outbreak", + "region_tag": "INT", + "lat": 46.23, + "lng": 6.14 + }, + { + "type": "rss", + "source": { + "source_id": "ecdc-epi-updates", + "authority_name": "ECDC Epidemiological Updates", + "country": "Sweden", + "country_code": "SE", + "region": "Europe", + "authority_type": "public_safety_program", + "base_url": "https://www.ecdc.europa.eu" + }, + "feed_url": "https://www.ecdc.europa.eu/en/taxonomy/term/1310/feed", + "category": "disease_outbreak", + "region_tag": "EU", + "lat": 59.35, + "lng": 18.10 + }, + { + "type": "rss", + "source": { + "source_id": "ecdc-risk-assessments", + "authority_name": "ECDC Risk Assessments", + "country": "Sweden", + "country_code": "SE", + "region": "Europe", + "authority_type": "public_safety_program", + "base_url": "https://www.ecdc.europa.eu" + }, + "feed_url": "https://www.ecdc.europa.eu/en/taxonomy/term/1295/feed", + "category": "disease_outbreak", + "region_tag": "EU", + "lat": 59.35, + "lng": 18.10 + }, + { + "type": "rss", + "source": { + "source_id": "cdc-newsroom", + "authority_name": "CDC Health Alerts", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "public_safety_program", + "base_url": "https://www.cdc.gov" + }, + "feed_url": "https://tools.cdc.gov/api/v2/resources/media/132608.rss", + "category": "disease_outbreak", + "region_tag": "US", + "lat": 33.80, + "lng": -84.39 + }, + { + "type": "rss", + "source": { + "source_id": "woah-animal-health", + "authority_name": "WOAH Animal Health", + "country": "France", + "country_code": "FR", + "region": "International", + "authority_type": "regulatory", + "base_url": "https://www.woah.org" + }, + "feed_url": "https://www.woah.org/en/feed/", + "category": "disease_outbreak", + "region_tag": "INT", + "lat": 48.86, + "lng": 2.32, + "include_keywords": ["outbreak", "avian", "influenza", "disease", "epidemic", "zoonotic", "virus", "pathogen", "infection", "surveillance", "alert", "emergency"] } ] diff --git a/src/index.css b/src/index.css index c1745fa..c075041 100644 --- a/src/index.css +++ b/src/index.css @@ -44,6 +44,8 @@ --color-cat-health: #4ca38c; --color-cat-intel: #7a6eab; --color-cat-emergency: #b85c4a; + --color-cat-environment: #4a8b6e; + --color-cat-disease: #c45e8a; } * { diff --git a/src/lib/severity.ts b/src/lib/severity.ts index 43068f1..d2691ab 100644 --- a/src/lib/severity.ts +++ b/src/lib/severity.ts @@ -53,6 +53,8 @@ export const categoryLabels: Record = { health_emergency: "Health Emergency", intelligence_report: "Intelligence Report", emergency_management: "Emergency Management", + environmental_disaster: "Environmental Disaster", + disease_outbreak: "Disease Outbreak", }; export const categoryOrder: AlertCategory[] = [ @@ -73,6 +75,8 @@ export const categoryOrder: AlertCategory[] = [ "health_emergency", "intelligence_report", "emergency_management", + "environmental_disaster", + "disease_outbreak", ]; /** @@ -97,6 +101,8 @@ export const categoryBadge: Record = { health_emergency: "bg-cat-health/15 text-cat-health border-cat-health/30", intelligence_report: "bg-cat-intel/15 text-cat-intel border-cat-intel/30", emergency_management: "bg-cat-emergency/15 text-cat-emergency border-cat-emergency/30", + environmental_disaster: "bg-cat-environment/15 text-cat-environment border-cat-environment/30", + disease_outbreak: "bg-cat-disease/15 text-cat-disease border-cat-disease/30", }; export const categoryIcons: Record = { @@ -117,6 +123,8 @@ export const categoryIcons: Record = { health_emergency: "HeartPulse", intelligence_report: "Eye", emergency_management: "Siren", + environmental_disaster: "CloudRain", + disease_outbreak: "Bug", }; export function freshnessLabel(hours: number): string { diff --git a/src/types/alert.ts b/src/types/alert.ts index d124d0f..b3ab794 100644 --- a/src/types/alert.ts +++ b/src/types/alert.ts @@ -23,7 +23,9 @@ export type AlertCategory = | "travel_warning" | "health_emergency" | "intelligence_report" - | "emergency_management"; + | "emergency_management" + | "environmental_disaster" + | "disease_outbreak"; export type AuthorityType = | "police" | "national_security" From 4fe5866fbc56474aafb338a3f7b1e7bdbde79673 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 23:23:57 +0100 Subject: [PATCH 36/58] =?UTF-8?q?feat:=20live=20registry=20hygiene=20?= =?UTF-8?q?=E2=80=94=20auto-merge,=20auto-reject=20dead=20sources,=20LLM?= =?UTF-8?q?=20category=20vetting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Source lifecycle is now fully automated without requiring restarts: - Every collector cycle merges the JSON registry into SQLite (new sources picked up, rejected status synced) - Dead sources (404, 403, DNS, TLS errors) are rejected in both SQLite AND the JSON registry, then written to the DLQ - Merge respects runtime rejections: if a source was killed at runtime, re-merging from JSON won't resurrect it - LLM vetting prompt now includes all 18 categories with descriptions so the model can assign the correct category for discovered sources - Verdict struct includes category field validated against the taxonomy --- docker-compose.yml | 2 + internal/collector/app/app.go | 1 + internal/collector/config/config.go | 3 ++ internal/collector/run/run.go | 83 +++++++++++++++++++++++++++++ internal/collector/vet/source.go | 46 ++++++++++++++-- internal/sourcedb/db.go | 21 ++++++-- 6 files changed, 149 insertions(+), 7 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 941340a..9e64c3c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,6 +12,8 @@ services: - ":3001" - --registry - /data/sources.db + - --registry-seed + - /app/registry/source_registry.json - --output - /data/alerts.json - --filtered-output diff --git a/internal/collector/app/app.go b/internal/collector/app/app.go index 352a3f0..f201acc 100644 --- a/internal/collector/app/app.go +++ b/internal/collector/app/app.go @@ -65,6 +65,7 @@ func Run(ctx context.Context, args []string, stdout io.Writer, stderr io.Writer) fs.BoolVar(&cfg.SourceDBMergeRegistry, "source-db-merge-registry", cfg.SourceDBMergeRegistry, "Merge a JSON registry or curated seed into the SQLite source database") fs.BoolVar(&cfg.SourceDBExportRegistry, "source-db-export-registry", cfg.SourceDBExportRegistry, "Export the SQLite source database back into the JSON registry") fs.StringVar(&cfg.CuratedSeedPath, "curated-seed", cfg.CuratedSeedPath, "Path to the curated agency seed JSON file") + fs.StringVar(&cfg.RegistrySeedPath, "registry-seed", cfg.RegistrySeedPath, "Path to the baked-in JSON registry for live merge on each cycle") fs.BoolVar(&cfg.APIEnabled, "api", cfg.APIEnabled, "Start the search API server alongside the collector") fs.StringVar(&cfg.APIAddr, "api-addr", cfg.APIAddr, "Listen address for the search API server") diff --git a/internal/collector/config/config.go b/internal/collector/config/config.go index a1a1441..e843562 100644 --- a/internal/collector/config/config.go +++ b/internal/collector/config/config.go @@ -73,6 +73,7 @@ type Config struct { SourceDBMergeRegistry bool SourceDBExportRegistry bool CuratedSeedPath string + RegistrySeedPath string CursorsPath string APIEnabled bool APIAddr string @@ -128,6 +129,7 @@ func Default() Config { SourceDBMergeRegistry: false, SourceDBExportRegistry: false, CuratedSeedPath: "registry/curated_agencies.seed.json", + RegistrySeedPath: "registry/source_registry.json", CursorsPath: "public/cursors.json", APIEnabled: false, APIAddr: ":3001", @@ -185,6 +187,7 @@ func FromEnv() Config { cfg.SourceDBMergeRegistry = envBool("SOURCE_DB_MERGE_REGISTRY", cfg.SourceDBMergeRegistry) cfg.SourceDBExportRegistry = envBool("SOURCE_DB_EXPORT_REGISTRY", cfg.SourceDBExportRegistry) cfg.CuratedSeedPath = envString("CURATED_SEED_PATH", cfg.CuratedSeedPath) + cfg.RegistrySeedPath = envString("REGISTRY_SEED_PATH", cfg.RegistrySeedPath) cfg.CursorsPath = envString("CURSORS_PATH", cfg.CursorsPath) cfg.APIEnabled = envBool("API_ENABLED", cfg.APIEnabled) cfg.APIAddr = envString("API_ADDR", cfg.APIAddr) diff --git a/internal/collector/run/run.go b/internal/collector/run/run.go index 0919653..92694da 100644 --- a/internal/collector/run/run.go +++ b/internal/collector/run/run.go @@ -9,6 +9,7 @@ import ( "fmt" "io" "net/url" + "os" "path/filepath" "strings" "time" @@ -73,6 +74,14 @@ func (r Runner) watch(ctx context.Context, cfg config.Config) error { } func (r Runner) runOnce(ctx context.Context, cfg config.Config) error { + // Live-merge the baked-in JSON registry into SQLite every cycle. + // This picks up new sources and syncs rejected status without restart. + if cfg.RegistrySeedPath != "" && isSQLitePath(cfg.RegistryPath) { + if err := r.mergeRegistry(ctx, cfg); err != nil { + fmt.Fprintf(r.stderr, "WARN registry merge: %v\n", err) + } + } + sources, err := registry.Load(cfg.RegistryPath) if err != nil { return err @@ -170,6 +179,11 @@ func (r Runner) runOnce(ctx context.Context, cfg config.Config) error { if err := deactivateReplacementSources(ctx, cfg.RegistryPath, replacementQueue); err != nil { return err } + if cfg.RegistrySeedPath != "" && len(replacementQueue) > 0 { + if err := rejectInJSONRegistry(cfg.RegistrySeedPath, replacementQueue); err != nil { + fmt.Fprintf(r.stderr, "WARN JSON registry reject: %v\n", err) + } + } if err := saveAlertState(ctx, cfg, fullState); err != nil { return err } @@ -763,6 +777,75 @@ func firstNonEmpty(values ...string) string { return "" } +func rejectInJSONRegistry(registryPath string, queue []model.SourceReplacementCandidate) error { + data, err := os.ReadFile(registryPath) + if err != nil { + return err + } + var entries []json.RawMessage + if err := json.Unmarshal(data, &entries); err != nil { + return err + } + + deadIDs := make(map[string]string, len(queue)) + for _, c := range queue { + deadIDs[c.SourceID] = c.Error + } + + modified := false + for i, raw := range entries { + var peek struct { + Source struct { + SourceID string `json:"source_id"` + } `json:"source"` + PromotionStatus string `json:"promotion_status"` + } + if err := json.Unmarshal(raw, &peek); err != nil { + continue + } + reason, isDead := deadIDs[peek.Source.SourceID] + if !isDead || peek.PromotionStatus == "rejected" { + continue + } + var obj map[string]any + if err := json.Unmarshal(raw, &obj); err != nil { + continue + } + obj["promotion_status"] = "rejected" + obj["rejection_reason"] = "Dead source: " + reason + updated, err := json.Marshal(obj) + if err != nil { + continue + } + entries[i] = updated + modified = true + } + + if !modified { + return nil + } + out, err := json.MarshalIndent(entries, "", " ") + if err != nil { + return err + } + out = append(out, '\n') + return os.WriteFile(registryPath, out, 0o644) +} + +func isSQLitePath(path string) bool { + ext := filepath.Ext(path) + return ext == ".db" || ext == ".sqlite" || ext == ".sqlite3" +} + +func (r Runner) mergeRegistry(ctx context.Context, cfg config.Config) error { + db, err := sourcedb.Open(cfg.RegistryPath) + if err != nil { + return err + } + defer db.Close() + return db.MergeRegistry(ctx, cfg.RegistrySeedPath) +} + func (r Runner) runDiscoveryLoop(ctx context.Context, cfg config.Config) { runOnce := func() { if err := discover.Run(ctx, cfg, r.stdout, r.stderr); err != nil && ctx.Err() == nil { diff --git a/internal/collector/vet/source.go b/internal/collector/vet/source.go index 0c4d178..61a63df 100644 --- a/internal/collector/vet/source.go +++ b/internal/collector/vet/source.go @@ -36,6 +36,7 @@ type Input struct { type Verdict struct { Approve bool `json:"approve"` PromotionStatus string `json:"promotion_status"` + Category string `json:"category,omitempty"` Level string `json:"level"` MissionTags []string `json:"mission_tags"` SourceQuality float64 `json:"source_quality"` @@ -72,12 +73,38 @@ func (v *Vetter) Evaluate(ctx context.Context, input Input) (Verdict, error) { content, err := v.client.Complete(ctx, []Message{ { - Role: "system", - Content: "You vet intelligence source candidates. Approve only operationally relevant sources: supranational, federal, or national level sources that publish actionable intelligence, wanted/missing/public appeals, cyber advisories, humanitarian security, crisis, war, organized crime, fraud, terrorism, or public-safety intelligence. Reject generic PR, speeches, institutional updates, local police, municipal news, or low-signal information. Return strict JSON only.", + Role: "system", + Content: `You vet intelligence source candidates for an OSINT dashboard. + +Approve only operationally relevant sources: supranational, federal, or national level sources that publish actionable intelligence — wanted/missing persons, public appeals, cyber advisories, vulnerability disclosures, humanitarian security, conflict monitoring, disease outbreaks, environmental disasters, fraud alerts, terrorism, travel warnings, emergency management, or public-safety intelligence. + +Reject: generic PR, speeches, institutional updates, local police, municipal news, marketing, newsletters, or low-signal content. + +Valid categories (pick the best match): +- cyber_advisory: vulnerability disclosures, patch advisories, threat intel from CERTs +- wanted_suspect: arrest warrants, wanted person notices +- missing_person: missing persons, AMBER alerts +- public_appeal: police witness calls, identification requests, crime tips +- fraud_alert: financial crime, scam warnings, sanctions, AML +- intelligence_report: strategic assessments, geopolitical analysis +- travel_warning: government travel advisories, consular warnings +- conflict_monitoring: armed conflict tracking, ceasefire violations, peace processes +- humanitarian_security: aid worker safety, access restrictions, crisis zones +- humanitarian_tasking: humanitarian missions, disaster response deployments +- health_emergency: disease outbreaks, pandemic updates, biosecurity +- disease_outbreak: epidemics, zoonotic diseases, outbreak surveillance +- environmental_disaster: earthquakes, oil spills, floods, wildfires, nuclear incidents, volcanic activity +- public_safety: civil protection, natural disaster warnings, emergency notifications +- emergency_management: disaster declarations, evacuation orders, crisis coordination +- terrorism_tip: counter-terrorism alerts, extremism threat assessments +- private_sector: corporate security, supply chain disruptions +- informational: general information, educational content + +Return strict JSON only with keys: approve, promotion_status, category, level, mission_tags, source_quality, operational_relevance, reason.`, }, { Role: "user", - Content: "Evaluate this discovered source and return JSON with keys approve, promotion_status, level, mission_tags, source_quality, operational_relevance, reason.\n\n" + string(payload), + Content: "Evaluate this discovered source and return JSON with keys approve, promotion_status, category, level, mission_tags, source_quality, operational_relevance, reason.\n\n" + string(payload), }, }) if err != nil { @@ -122,6 +149,15 @@ func decodeVerdict(content string) (Verdict, error) { return verdict, nil } +var validCategories = map[string]bool{ + "cyber_advisory": true, "wanted_suspect": true, "missing_person": true, + "public_appeal": true, "fraud_alert": true, "intelligence_report": true, + "travel_warning": true, "conflict_monitoring": true, "humanitarian_security": true, + "humanitarian_tasking": true, "health_emergency": true, "disease_outbreak": true, + "environmental_disaster": true, "public_safety": true, "emergency_management": true, + "terrorism_tip": true, "private_sector": true, "informational": true, +} + func (v *Verdict) normalize() { v.PromotionStatus = strings.ToLower(strings.TrimSpace(v.PromotionStatus)) switch v.PromotionStatus { @@ -133,6 +169,10 @@ func (v *Verdict) normalize() { v.PromotionStatus = "rejected" } } + v.Category = strings.ToLower(strings.TrimSpace(v.Category)) + if !validCategories[v.Category] { + v.Category = "" + } v.Level = strings.ToLower(strings.TrimSpace(v.Level)) switch v.Level { case "international", "supranational", "federal", "national", "regional", "local": diff --git a/internal/sourcedb/db.go b/internal/sourcedb/db.go index b51dc14..3ec3c1c 100644 --- a/internal/sourcedb/db.go +++ b/internal/sourcedb/db.go @@ -718,9 +718,11 @@ func (db *DB) DeactivateSources(ctx context.Context, reasons map[string]string) if _, err := tx.ExecContext(ctx, ` UPDATE sources SET status = 'needs_replacement', + promotion_status = 'rejected', + rejection_reason = ?, last_error = ?, updated_at = CURRENT_TIMESTAMP -WHERE id = ?`, strings.TrimSpace(reason), sourceID); err != nil { +WHERE id = ?`, "Dead source: "+strings.TrimSpace(reason), strings.TrimSpace(reason), sourceID); err != nil { return fmt.Errorf("deactivate source %s: %w", sourceID, err) } } @@ -976,15 +978,26 @@ ON CONFLICT(id) DO UPDATE SET include_keywords_json = excluded.include_keywords_json, exclude_keywords_json = excluded.exclude_keywords_json, source_quality = excluded.source_quality, - promotion_status = excluded.promotion_status, - rejection_reason = excluded.rejection_reason, + promotion_status = CASE + WHEN excluded.promotion_status = 'rejected' THEN 'rejected' + WHEN sources.promotion_status = 'rejected' AND excluded.promotion_status IN ('active', '') THEN 'rejected' + ELSE excluded.promotion_status + END, + rejection_reason = CASE + WHEN excluded.promotion_status = 'rejected' THEN excluded.rejection_reason + WHEN sources.promotion_status = 'rejected' AND excluded.promotion_status IN ('active', '') THEN sources.rejection_reason + ELSE excluded.rejection_reason + END, is_mirror = excluded.is_mirror, preferred_source_rank = excluded.preferred_source_rank, reporting_label = excluded.reporting_label, reporting_url = excluded.reporting_url, reporting_phone = excluded.reporting_phone, reporting_notes = excluded.reporting_notes, - status = 'active', + status = CASE + WHEN sources.promotion_status = 'rejected' AND excluded.promotion_status IN ('active', '') THEN sources.status + ELSE 'active' + END, updated_at = CURRENT_TIMESTAMP `, src.Source.SourceID, From 05902868adc35de547daab992e6ac9ce73655651 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 23:26:13 +0100 Subject: [PATCH 37/58] fix: dev-stop and dev-restart now remove volumes for clean DB rebuild Add -v flag to docker-compose down so feed-data volume is removed, ensuring the entrypoint re-seeds the DB from the current JSON registry on next start. --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index cb6eaed..7d77ac8 100644 --- a/Makefile +++ b/Makefile @@ -127,13 +127,13 @@ dev-start: ## Start the local HTTP dev stack on localhost @echo "EUOSINT available at http://localhost:$${EUOSINT_HTTP_PORT:-8080}" @open "http://localhost:$${EUOSINT_HTTP_PORT:-8080}" -dev-stop: ## Stop the local dev stack and prune dangling images - $(DOCKER_COMPOSE) down --remove-orphans +dev-stop: ## Stop the local dev stack, remove feed-data volume and prune images + $(DOCKER_COMPOSE) down --remove-orphans -v @docker image prune -f --filter "label=com.docker.compose.project" >/dev/null 2>&1 || true @docker builder prune -f >/dev/null 2>&1 || true -dev-restart: ## Restart the local dev stack (prunes old images first) - $(DOCKER_COMPOSE) down --remove-orphans +dev-restart: ## Restart the local dev stack (removes volumes, rebuilds from scratch) + $(DOCKER_COMPOSE) down --remove-orphans -v @docker image prune -f --filter "label=com.docker.compose.project" >/dev/null 2>&1 || true @docker builder prune -f >/dev/null 2>&1 || true $(DOCKER_COMPOSE) up --build -d From 0952795af5a976c3248891b14f81e6da785471c8 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 23:44:05 +0100 Subject: [PATCH 38/58] chore: update search topic labels, add DLQ sync script, clean up run.go Add all 18 category labels to LLM search discovery for replacement feed lookups. Remove dead rejectInJSONRegistry (wrote to Docker ephemeral FS). Add scripts/apply-dlq.py and Makefile dev-sync-dlq target for developer-side DLQ processing. --- Makefile | 6 +++ internal/collector/discover/search_llm.go | 16 +++++- internal/collector/run/run.go | 61 ----------------------- scripts/apply-dlq.py | 53 ++++++++++++++++++++ 4 files changed, 74 insertions(+), 62 deletions(-) create mode 100644 scripts/apply-dlq.py diff --git a/Makefile b/Makefile index 7d77ac8..dd62160 100644 --- a/Makefile +++ b/Makefile @@ -143,6 +143,12 @@ dev-restart: ## Restart the local dev stack (removes volumes, rebuilds from scra dev-sync-registry: ## Merge source_registry.json into the running DB (adds new feeds) $(DOCKER_COMPOSE) exec collector euosint-collector --source-db /data/sources.db --curated-seed /app/registry/source_registry.json --source-db-merge-registry +dev-sync-dlq: ## Copy the dead-letter queue from the running container to update the local JSON registry + @docker cp euosint-collector-1:/data/source_dead_letter.json .tmp/dlq.json 2>/dev/null && \ + python3 scripts/apply-dlq.py registry/source_registry.json .tmp/dlq.json && \ + echo "DLQ applied — review changes with: git diff registry/source_registry.json" || \ + echo "No DLQ data or container not running" + dev-logs: ## Tail local dev stack logs $(DOCKER_COMPOSE) logs -f --tail=200 diff --git a/internal/collector/discover/search_llm.go b/internal/collector/discover/search_llm.go index f3d7a2c..b140840 100644 --- a/internal/collector/discover/search_llm.go +++ b/internal/collector/discover/search_llm.go @@ -164,7 +164,7 @@ func searchTopicLabel(category string, authorityType string) string { return "missing persons and missing children" case "wanted_suspect": return "wanted persons, fugitives, and public appeals" - case "terror_warning": + case "terror_warning", "terrorism_tip": return "terrorism warnings and threat notices" case "organized_crime": return "organized crime and major criminal investigations" @@ -174,6 +174,20 @@ func searchTopicLabel(category string, authorityType string) string { return "cyber advisories and security alerts" case "public_appeal": return "public appeals, wanted persons, and missing persons" + case "fraud_alert": + return "fraud alerts, financial crime warnings, and sanctions notices" + case "intelligence_report": + return "strategic intelligence assessments and geopolitical analysis" + case "conflict_monitoring": + return "armed conflict tracking, ceasefire monitoring, and peace processes" + case "humanitarian_security", "humanitarian_tasking": + return "humanitarian operations, aid worker security, and crisis coordination" + case "health_emergency", "disease_outbreak": + return "disease outbreaks, epidemics, pandemic surveillance, and public health emergencies" + case "environmental_disaster": + return "environmental disasters, earthquakes, oil spills, volcanic activity, and nuclear incidents" + case "public_safety", "emergency_management": + return "civil protection, emergency management, and natural disaster warnings" default: if strings.TrimSpace(authorityType) != "" { return authorityType + " intelligence collection" diff --git a/internal/collector/run/run.go b/internal/collector/run/run.go index 92694da..c7992ae 100644 --- a/internal/collector/run/run.go +++ b/internal/collector/run/run.go @@ -9,7 +9,6 @@ import ( "fmt" "io" "net/url" - "os" "path/filepath" "strings" "time" @@ -179,11 +178,6 @@ func (r Runner) runOnce(ctx context.Context, cfg config.Config) error { if err := deactivateReplacementSources(ctx, cfg.RegistryPath, replacementQueue); err != nil { return err } - if cfg.RegistrySeedPath != "" && len(replacementQueue) > 0 { - if err := rejectInJSONRegistry(cfg.RegistrySeedPath, replacementQueue); err != nil { - fmt.Fprintf(r.stderr, "WARN JSON registry reject: %v\n", err) - } - } if err := saveAlertState(ctx, cfg, fullState); err != nil { return err } @@ -777,61 +771,6 @@ func firstNonEmpty(values ...string) string { return "" } -func rejectInJSONRegistry(registryPath string, queue []model.SourceReplacementCandidate) error { - data, err := os.ReadFile(registryPath) - if err != nil { - return err - } - var entries []json.RawMessage - if err := json.Unmarshal(data, &entries); err != nil { - return err - } - - deadIDs := make(map[string]string, len(queue)) - for _, c := range queue { - deadIDs[c.SourceID] = c.Error - } - - modified := false - for i, raw := range entries { - var peek struct { - Source struct { - SourceID string `json:"source_id"` - } `json:"source"` - PromotionStatus string `json:"promotion_status"` - } - if err := json.Unmarshal(raw, &peek); err != nil { - continue - } - reason, isDead := deadIDs[peek.Source.SourceID] - if !isDead || peek.PromotionStatus == "rejected" { - continue - } - var obj map[string]any - if err := json.Unmarshal(raw, &obj); err != nil { - continue - } - obj["promotion_status"] = "rejected" - obj["rejection_reason"] = "Dead source: " + reason - updated, err := json.Marshal(obj) - if err != nil { - continue - } - entries[i] = updated - modified = true - } - - if !modified { - return nil - } - out, err := json.MarshalIndent(entries, "", " ") - if err != nil { - return err - } - out = append(out, '\n') - return os.WriteFile(registryPath, out, 0o644) -} - func isSQLitePath(path string) bool { ext := filepath.Ext(path) return ext == ".db" || ext == ".sqlite" || ext == ".sqlite3" diff --git a/scripts/apply-dlq.py b/scripts/apply-dlq.py new file mode 100644 index 0000000..5749b3a --- /dev/null +++ b/scripts/apply-dlq.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +"""Apply dead-letter queue rejections to the local JSON registry. + +Usage: python3 scripts/apply-dlq.py registry/source_registry.json .tmp/dlq.json +""" +import json +import sys + + +def main(): + if len(sys.argv) < 3: + print(f"Usage: {sys.argv[0]} ", file=sys.stderr) + sys.exit(1) + + registry_path, dlq_path = sys.argv[1], sys.argv[2] + + with open(dlq_path) as f: + dlq = json.load(f) + + dead_sources = {} + for src in dlq.get("sources", []): + sid = src.get("source_id", "") + if sid: + dead_sources[sid] = src.get("error", "unknown error") + + if not dead_sources: + print("DLQ is empty, nothing to apply.") + return + + with open(registry_path) as f: + registry = json.load(f) + + changed = 0 + for entry in registry: + sid = entry.get("source", {}).get("source_id", "") + if sid in dead_sources and entry.get("promotion_status") != "rejected": + entry["promotion_status"] = "rejected" + entry["rejection_reason"] = f"Dead source: {dead_sources[sid]}" + changed += 1 + + if changed == 0: + print("No new rejections to apply.") + return + + with open(registry_path, "w") as f: + json.dump(registry, f, indent=2, ensure_ascii=False) + f.write("\n") + + print(f"Rejected {changed} dead source(s) in {registry_path}") + + +if __name__ == "__main__": + main() From 99fe58f7e6e337654d763998fde3550c91e9a963 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 23:45:55 +0100 Subject: [PATCH 39/58] =?UTF-8?q?chore:=20reject=20European=20Schoolnet=20?= =?UTF-8?q?=E2=80=94=20educational,=20not=20intelligence?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- registry/source_registry.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/registry/source_registry.json b/registry/source_registry.json index 42f1bfc..e0edbb5 100644 --- a/registry/source_registry.json +++ b/registry/source_registry.json @@ -5420,6 +5420,25 @@ "lat": 50.11, "lng": 8.68 }, + { + "type": "rss", + "promotion_status": "rejected", + "rejection_reason": "Educational network for schools, not an intelligence source", + "source": { + "source_id": "european-schoolnet", + "authority_name": "European Schoolnet", + "country": "Belgium", + "country_code": "BE", + "region": "Europe", + "authority_type": "educational", + "base_url": "https://www.eun.org" + }, + "feed_url": "https://www.eun.org/rss", + "category": "informational", + "region_tag": "EU", + "lat": 50.85, + "lng": 4.35 + }, { "type": "rss", "source": { From e223283c069b9a6b2764ca94504ce7ef20b1f49f Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Mon, 16 Mar 2026 23:49:54 +0100 Subject: [PATCH 40/58] feat: pre-seeded DB distribution for new installs Add make dev-export-db to snapshot sources.db from a running collector. Entrypoint prefers sources.seed.db over cold init+import when available. The merge step still runs on every start to pick up JSON registry updates. --- Makefile | 6 ++++++ docker/collector-entrypoint.sh | 13 +++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index dd62160..8957ebb 100644 --- a/Makefile +++ b/Makefile @@ -143,6 +143,12 @@ dev-restart: ## Restart the local dev stack (removes volumes, rebuilds from scra dev-sync-registry: ## Merge source_registry.json into the running DB (adds new feeds) $(DOCKER_COMPOSE) exec collector euosint-collector --source-db /data/sources.db --curated-seed /app/registry/source_registry.json --source-db-merge-registry +dev-export-db: ## Export seeded sources.db from running container for distribution + @mkdir -p registry + @docker cp euosint-collector-1:/data/sources.db registry/sources.seed.db 2>/dev/null && \ + echo "Exported registry/sources.seed.db ($$(wc -c < registry/sources.seed.db | tr -d ' ') bytes)" || \ + echo "Container not running or no DB found" + dev-sync-dlq: ## Copy the dead-letter queue from the running container to update the local JSON registry @docker cp euosint-collector-1:/data/source_dead_letter.json .tmp/dlq.json 2>/dev/null && \ python3 scripts/apply-dlq.py registry/source_registry.json .tmp/dlq.json && \ diff --git a/docker/collector-entrypoint.sh b/docker/collector-entrypoint.sh index 2579a10..59ac153 100644 --- a/docker/collector-entrypoint.sh +++ b/docker/collector-entrypoint.sh @@ -22,10 +22,15 @@ seed_if_missing /app/public-defaults/source-health.json /data/source-health.json seed_if_missing /app/registry/source_candidates.json /data/source_candidates.json if [ ! -f /data/sources.db ]; then - euosint-collector --source-db /data/sources.db --source-db-init - euosint-collector --source-db /data/sources.db --registry /app/registry/source_registry.json --source-db-import-registry - if [ -f /app/registry/curated_agencies.seed.json ]; then - euosint-collector --source-db /data/sources.db --curated-seed /app/registry/curated_agencies.seed.json --source-db-merge-registry + if [ -f /app/registry/sources.seed.db ]; then + cp /app/registry/sources.seed.db /data/sources.db + echo "Seeded sources.db from pre-built snapshot" + else + euosint-collector --source-db /data/sources.db --source-db-init + euosint-collector --source-db /data/sources.db --registry /app/registry/source_registry.json --source-db-import-registry + if [ -f /app/registry/curated_agencies.seed.json ]; then + euosint-collector --source-db /data/sources.db --curated-seed /app/registry/curated_agencies.seed.json --source-db-merge-registry + fi fi fi From 0e7a62471ef9a211784a382d4cbc440dbcde833b Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Tue, 17 Mar 2026 08:08:51 +0100 Subject: [PATCH 41/58] =?UTF-8?q?feat:=203-tier=20geocoding=20pipeline=20?= =?UTF-8?q?=E2=80=94=20city=20DB,=20Nominatim,=20capital=20coords?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tier 1: GeoNames cities500.txt (200k+ cities) imported into SQLite for fast city-name lookups. Text is scanned for place names and matched against the DB with population-based disambiguation. Tier 2: OSM Nominatim fallback for place names not in the local DB. Rate-limited (1 req/sec), in-memory cached, configurable base URL for self-hosted instances. Tier 3: Country-level text scanning now returns capital city coordinates instead of geographic centroids. Fixes island nations (Malta, Cyprus, Singapore, etc.) placing alerts in the sea. The Dockerfile downloads cities500.txt at build time (~30MB). The collector auto-imports it into SQLite on first run. All tiers are optional — the system degrades gracefully. --- .gitignore | 3 + Dockerfile.collector | 7 + docker-compose.yml | 2 + internal/collector/config/config.go | 9 + internal/collector/normalize/geocode.go | 15 +- .../collector/normalize/geocode_capitals.go | 163 ++++++++++ .../collector/normalize/geocode_nominatim.go | 179 +++++++++++ internal/collector/normalize/geocoder.go | 282 ++++++++++++++++++ internal/collector/normalize/geocoder_test.go | 176 +++++++++++ internal/collector/normalize/normalize.go | 45 ++- internal/collector/run/run.go | 59 +++- internal/sourcedb/geocode.go | 164 ++++++++++ internal/sourcedb/schema.sql | 15 + 13 files changed, 1110 insertions(+), 9 deletions(-) create mode 100644 internal/collector/normalize/geocode_capitals.go create mode 100644 internal/collector/normalize/geocode_nominatim.go create mode 100644 internal/collector/normalize/geocoder.go create mode 100644 internal/collector/normalize/geocoder_test.go create mode 100644 internal/sourcedb/geocode.go diff --git a/.gitignore b/.gitignore index 4aa4548..9ce4abc 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,9 @@ docker-compose.override.yml *.sln *.sw? +# GeoNames dataset (downloaded at build time, ~30MB) +registry/cities500.txt + # Tool caches .eslintcache .npm/ diff --git a/Dockerfile.collector b/Dockerfile.collector index 5afd1cd..8ac19b7 100644 --- a/Dockerfile.collector +++ b/Dockerfile.collector @@ -14,6 +14,12 @@ COPY public ./public RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /out/euosint-collector ./cmd/euosint-collector +FROM alpine:3.20 AS geonames +RUN apk add --no-cache curl unzip +RUN curl -sL https://download.geonames.org/export/dump/cities500.zip -o /tmp/cities500.zip \ + && unzip /tmp/cities500.zip -d /tmp \ + && rm /tmp/cities500.zip + FROM alpine:3.20 RUN apk add --no-cache ca-certificates chromium @@ -22,6 +28,7 @@ ENV CHROME_PATH=/usr/bin/chromium-browser WORKDIR /app COPY --from=build /out/euosint-collector /usr/local/bin/euosint-collector +COPY --from=geonames /tmp/cities500.txt ./registry/cities500.txt COPY registry ./registry COPY public ./public-defaults COPY docker/collector-entrypoint.sh /usr/local/bin/collector-entrypoint.sh diff --git a/docker-compose.yml b/docker-compose.yml index 9e64c3c..de75e03 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -27,6 +27,8 @@ services: - --replacement-queue - /data/source_dead_letter.json environment: + GEONAMES_PATH: "/app/registry/cities500.txt" + NOMINATIM_ENABLED: "1" INTERVAL_MS: "900000" MAX_PER_SOURCE: "40" MISSING_PERSON_RELEVANCE_THRESHOLD: "0" diff --git a/internal/collector/config/config.go b/internal/collector/config/config.go index e843562..a532fc5 100644 --- a/internal/collector/config/config.go +++ b/internal/collector/config/config.go @@ -75,6 +75,9 @@ type Config struct { CuratedSeedPath string RegistrySeedPath string CursorsPath string + GeoNamesPath string + NominatimBaseURL string + NominatimEnabled bool APIEnabled bool APIAddr string } @@ -131,6 +134,9 @@ func Default() Config { CuratedSeedPath: "registry/curated_agencies.seed.json", RegistrySeedPath: "registry/source_registry.json", CursorsPath: "public/cursors.json", + GeoNamesPath: "registry/cities500.txt", + NominatimBaseURL: "https://nominatim.openstreetmap.org", + NominatimEnabled: true, APIEnabled: false, APIAddr: ":3001", } @@ -189,6 +195,9 @@ func FromEnv() Config { cfg.CuratedSeedPath = envString("CURATED_SEED_PATH", cfg.CuratedSeedPath) cfg.RegistrySeedPath = envString("REGISTRY_SEED_PATH", cfg.RegistrySeedPath) cfg.CursorsPath = envString("CURSORS_PATH", cfg.CursorsPath) + cfg.GeoNamesPath = envString("GEONAMES_PATH", cfg.GeoNamesPath) + cfg.NominatimBaseURL = envString("NOMINATIM_BASE_URL", cfg.NominatimBaseURL) + cfg.NominatimEnabled = envBool("NOMINATIM_ENABLED", cfg.NominatimEnabled) cfg.APIEnabled = envBool("API_ENABLED", cfg.APIEnabled) cfg.APIAddr = envString("API_ADDR", cfg.APIAddr) return cfg diff --git a/internal/collector/normalize/geocode.go b/internal/collector/normalize/geocode.go index bac1330..4fb9fc4 100644 --- a/internal/collector/normalize/geocode.go +++ b/internal/collector/normalize/geocode.go @@ -99,6 +99,7 @@ var geoCountries = []countryGeo{ {"Malawi", "MW", -13.25, 34.30}, {"Malaysia", "MY", 4.21, 101.98}, {"Mali", "ML", 17.57, -4.00}, + {"Malta", "MT", 35.90, 14.51}, {"Mauritania", "MR", 21.01, -10.94}, {"Mexico", "MX", 23.63, -102.55}, {"Moldova", "MD", 47.41, 28.37}, @@ -222,6 +223,7 @@ var geoAliases = map[string]string{ "malawian": "Malawi", "malaysian": "Malaysia", "malian": "Mali", + "maltese": "Malta", "mauritanian": "Mauritania", "mexican": "Mexico", "moldovan": "Moldova", @@ -333,6 +335,7 @@ var geoAliases = map[string]string{ "hodeida": "Yemen", "hodeidah": "Yemen", "taipei": "Taiwan", + "valletta": "Malta", "kyiv": "Ukraine", "kharkiv": "Ukraine", } @@ -354,9 +357,19 @@ func init() { } } -// geocodeCountryCode returns the centroid for a 2-letter country code. +// geocodeCountryCode returns the capital city coordinates for a 2-letter +// country code, falling back to geographic centroid if no capital is known. func geocodeCountryCode(code string) (lat, lng float64, name string, ok bool) { code = strings.ToUpper(strings.TrimSpace(code)) + // Prefer capital city coords (fixes islands-in-water problem). + if capital, cok := capitalCoords[code]; cok { + for i := range geoCountries { + if geoCountries[i].Code == code { + return capital[0], capital[1], geoCountries[i].Name, true + } + } + return capital[0], capital[1], code, true + } for i := range geoCountries { if geoCountries[i].Code == code { return geoCountries[i].Lat, geoCountries[i].Lng, geoCountries[i].Name, true diff --git a/internal/collector/normalize/geocode_capitals.go b/internal/collector/normalize/geocode_capitals.go new file mode 100644 index 0000000..ee2a524 --- /dev/null +++ b/internal/collector/normalize/geocode_capitals.go @@ -0,0 +1,163 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package normalize + +// capitalCoords maps ISO 3166-1 alpha-2 codes to capital city coordinates. +// Used instead of geographic centroids so island nations (Malta, Cyprus, +// Singapore, etc.) place pins on land rather than in the sea. +var capitalCoords = map[string][2]float64{ + "AF": {34.53, 69.17}, // Kabul + "AL": {41.33, 19.82}, // Tirana + "DZ": {36.75, 3.04}, // Algiers + "AO": {-8.84, 13.23}, // Luanda + "AR": {-34.60, -58.38}, // Buenos Aires + "AM": {40.18, 44.51}, // Yerevan + "AU": {-35.28, 149.13}, // Canberra + "AT": {48.21, 16.37}, // Vienna + "AZ": {40.41, 49.87}, // Baku + "BH": {26.23, 50.59}, // Manama + "BD": {23.81, 90.41}, // Dhaka + "BY": {53.90, 27.57}, // Minsk + "BE": {50.85, 4.35}, // Brussels + "BJ": {6.50, 2.60}, // Porto-Novo + "BO": {-16.50, -68.15}, // La Paz + "BA": {43.86, 18.41}, // Sarajevo + "BW": {-24.65, 25.91}, // Gaborone + "BR": {-15.79, -47.88}, // Brasília + "BG": {42.70, 23.32}, // Sofia + "BF": {12.37, -1.52}, // Ouagadougou + "BI": {-3.38, 29.36}, // Gitega + "KH": {11.56, 104.92}, // Phnom Penh + "CM": {3.87, 11.52}, // Yaoundé + "CA": {45.42, -75.70}, // Ottawa + "CF": {4.39, 18.56}, // Bangui + "TD": {12.13, 15.05}, // N'Djamena + "CL": {-33.45, -70.67}, // Santiago + "CN": {39.90, 116.40}, // Beijing + "CO": {4.71, -74.07}, // Bogotá + "CD": {-4.32, 15.31}, // Kinshasa + "CR": {9.93, -84.09}, // San José + "HR": {45.81, 15.98}, // Zagreb + "CU": {23.11, -82.37}, // Havana + "CY": {35.17, 33.36}, // Nicosia + "CZ": {50.08, 14.43}, // Prague + "DK": {55.68, 12.57}, // Copenhagen + "DO": {18.47, -69.90}, // Santo Domingo + "EC": {-0.18, -78.47}, // Quito + "EG": {30.04, 31.24}, // Cairo + "SV": {13.69, -89.19}, // San Salvador + "ER": {15.34, 38.93}, // Asmara + "EE": {59.44, 24.75}, // Tallinn + "ET": {9.02, 38.75}, // Addis Ababa + "FI": {60.17, 24.94}, // Helsinki + "FR": {48.86, 2.35}, // Paris + "GA": {0.39, 9.45}, // Libreville + "GM": {13.45, -16.58}, // Banjul + "PS": {31.90, 35.20}, // Ramallah + "GE": {41.72, 44.79}, // Tbilisi + "DE": {52.52, 13.41}, // Berlin + "GH": {5.56, -0.19}, // Accra + "GR": {37.98, 23.73}, // Athens + "GT": {14.63, -90.51}, // Guatemala City + "GN": {9.64, -13.58}, // Conakry + "HT": {18.54, -72.34}, // Port-au-Prince + "HN": {14.07, -87.19}, // Tegucigalpa + "HU": {47.50, 19.04}, // Budapest + "IN": {28.61, 77.21}, // New Delhi + "ID": {-6.21, 106.85}, // Jakarta + "IR": {35.69, 51.39}, // Tehran + "IQ": {33.34, 44.37}, // Baghdad + "IE": {53.35, -6.26}, // Dublin + "IL": {31.77, 35.22}, // Jerusalem + "IT": {41.90, 12.50}, // Rome + "CI": {6.83, -5.29}, // Yamoussoukro + "JM": {18.00, -76.79}, // Kingston + "JP": {35.68, 139.69}, // Tokyo + "JO": {31.95, 35.93}, // Amman + "KZ": {51.17, 71.43}, // Astana + "KE": {-1.29, 36.82}, // Nairobi + "XK": {42.66, 21.17}, // Pristina + "KW": {29.37, 47.98}, // Kuwait City + "KG": {42.87, 74.59}, // Bishkek + "LA": {17.97, 102.63}, // Vientiane + "LV": {56.95, 24.11}, // Riga + "LB": {33.89, 35.50}, // Beirut + "LY": {32.90, 13.18}, // Tripoli + "LT": {54.69, 25.28}, // Vilnius + "LU": {49.61, 6.13}, // Luxembourg City + "MG": {-18.91, 47.54}, // Antananarivo + "MW": {-13.97, 33.79}, // Lilongwe + "MY": {3.14, 101.69}, // Kuala Lumpur + "ML": {12.64, -8.00}, // Bamako + "MT": {35.90, 14.51}, // Valletta + "MR": {18.09, -15.98}, // Nouakchott + "MX": {19.43, -99.13}, // Mexico City + "MD": {47.01, 28.86}, // Chișinău + "MN": {47.91, 106.91}, // Ulaanbaatar + "ME": {42.44, 19.26}, // Podgorica + "MA": {34.02, -6.84}, // Rabat + "MZ": {-25.97, 32.57}, // Maputo + "MM": {19.76, 96.07}, // Naypyidaw + "NA": {-22.56, 17.08}, // Windhoek + "NP": {27.72, 85.32}, // Kathmandu + "NL": {52.37, 4.89}, // Amsterdam + "NZ": {-41.29, 174.78}, // Wellington + "NI": {12.11, -86.27}, // Managua + "NE": {13.51, 2.11}, // Niamey + "NG": {9.06, 7.49}, // Abuja + "KP": {39.02, 125.75}, // Pyongyang + "MK": {42.00, 21.43}, // Skopje + "NO": {59.91, 10.75}, // Oslo + "OM": {23.59, 58.54}, // Muscat + "PK": {33.69, 73.04}, // Islamabad + "PA": {8.98, -79.52}, // Panama City + "PG": {-6.31, 147.15}, // Port Moresby + "PY": {-25.26, -57.58}, // Asunción + "PE": {-12.05, -77.04}, // Lima + "PH": {14.60, 120.98}, // Manila + "PL": {52.23, 21.01}, // Warsaw + "PT": {38.72, -9.14}, // Lisbon + "QA": {25.29, 51.53}, // Doha + "RO": {44.43, 26.10}, // Bucharest + "RU": {55.76, 37.62}, // Moscow + "RW": {-1.94, 30.06}, // Kigali + "SA": {24.69, 46.72}, // Riyadh + "SN": {14.72, -17.47}, // Dakar + "RS": {44.79, 20.47}, // Belgrade + "SL": {8.48, -13.23}, // Freetown + "SG": {1.29, 103.85}, // Singapore + "SK": {48.15, 17.11}, // Bratislava + "SI": {46.06, 14.51}, // Ljubljana + "SO": {2.05, 45.32}, // Mogadishu + "ZA": {-25.75, 28.19}, // Pretoria + "KR": {37.57, 126.98}, // Seoul + "SS": {4.85, 31.60}, // Juba + "ES": {40.42, -3.70}, // Madrid + "LK": {6.93, 79.85}, // Colombo + "SD": {15.60, 32.53}, // Khartoum + "SE": {59.33, 18.07}, // Stockholm + "CH": {46.95, 7.45}, // Bern + "SY": {33.51, 36.28}, // Damascus + "TW": {25.03, 121.57}, // Taipei + "TJ": {38.56, 68.77}, // Dushanbe + "TZ": {-6.16, 35.75}, // Dodoma + "TH": {13.76, 100.50}, // Bangkok + "TG": {6.14, 1.21}, // Lomé + "TN": {36.81, 10.17}, // Tunis + "TR": {39.93, 32.87}, // Ankara + "TM": {37.95, 58.38}, // Ashgabat + "UG": {0.35, 32.58}, // Kampala + "UA": {50.45, 30.52}, // Kyiv + "AE": {24.45, 54.65}, // Abu Dhabi + "GB": {51.51, -0.13}, // London + "US": {38.90, -77.04}, // Washington D.C. + "UY": {-34.88, -56.17}, // Montevideo + "UZ": {41.30, 69.28}, // Tashkent + "VE": {10.49, -66.88}, // Caracas + "VN": {21.03, 105.85}, // Hanoi + "YE": {15.37, 44.21}, // Sana'a + "ZM": {-15.39, 28.32}, // Lusaka + "ZW": {-17.83, 31.05}, // Harare + "IS": {64.15, -21.94}, // Reykjavik +} diff --git a/internal/collector/normalize/geocode_nominatim.go b/internal/collector/normalize/geocode_nominatim.go new file mode 100644 index 0000000..29ddf99 --- /dev/null +++ b/internal/collector/normalize/geocode_nominatim.go @@ -0,0 +1,179 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package normalize + +import ( + "context" + "encoding/json" + "io" + "net/http" + "net/url" + "strconv" + "strings" + "sync" + "time" +) + +// NominatimResult is a geocoding result from OpenStreetMap Nominatim. +type NominatimResult struct { + Lat float64 + Lng float64 + CountryCode string + DisplayName string +} + +// NominatimClient queries the OSM Nominatim API for geocoding. +// It enforces the 1 request/second rate limit for the public instance. +type NominatimClient struct { + baseURL string + userAgent string + client *http.Client + + mu sync.Mutex + lastCall time.Time + + // Simple in-memory cache to avoid re-querying the same place name. + cacheMu sync.RWMutex + cache map[string]*nominatimCacheEntry +} + +type nominatimCacheEntry struct { + result NominatimResult + ok bool +} + +type nominatimAPIResponse struct { + Lat string `json:"lat"` + Lon string `json:"lon"` + DisplayName string `json:"display_name"` + Address struct { + CountryCode string `json:"country_code"` + } `json:"address"` +} + +// NewNominatimClient creates a Nominatim geocoding client. +// baseURL defaults to the public OSM Nominatim if empty. +func NewNominatimClient(baseURL string, userAgent string) *NominatimClient { + if baseURL == "" { + baseURL = "https://nominatim.openstreetmap.org" + } + if userAgent == "" { + userAgent = "EUOSINTBot/1.0 (https://www.scalytics.io; ops@scalytics.io)" + } + return &NominatimClient{ + baseURL: strings.TrimRight(baseURL, "/"), + userAgent: userAgent, + client: &http.Client{Timeout: 10 * time.Second}, + cache: make(map[string]*nominatimCacheEntry, 256), + } +} + +// Geocode looks up a place name and returns coordinates. +func (n *NominatimClient) Geocode(ctx context.Context, query string, countryCode string) (NominatimResult, bool) { + query = strings.TrimSpace(query) + if query == "" { + return NominatimResult{}, false + } + + cacheKey := strings.ToLower(query) + "|" + strings.ToUpper(countryCode) + n.cacheMu.RLock() + if entry, ok := n.cache[cacheKey]; ok { + n.cacheMu.RUnlock() + return entry.result, entry.ok + } + n.cacheMu.RUnlock() + + // Rate limit: 1 req/sec for public Nominatim. + n.mu.Lock() + since := time.Since(n.lastCall) + if since < time.Second { + time.Sleep(time.Second - since) + } + n.lastCall = time.Now() + n.mu.Unlock() + + params := url.Values{ + "q": {query}, + "format": {"json"}, + "limit": {"1"}, + "addressdetails": {"1"}, + "accept-language": {"en"}, + } + if cc := strings.TrimSpace(countryCode); cc != "" { + params.Set("countrycodes", strings.ToLower(cc)) + } + + reqURL := n.baseURL + "/search?" + params.Encode() + req, err := http.NewRequestWithContext(ctx, "GET", reqURL, nil) + if err != nil { + n.cacheNegative(cacheKey) + return NominatimResult{}, false + } + req.Header.Set("User-Agent", n.userAgent) + + resp, err := n.client.Do(req) + if err != nil { + n.cacheNegative(cacheKey) + return NominatimResult{}, false + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + n.cacheNegative(cacheKey) + return NominatimResult{}, false + } + + body, err := io.ReadAll(io.LimitReader(resp.Body, 64*1024)) + if err != nil { + n.cacheNegative(cacheKey) + return NominatimResult{}, false + } + + var results []nominatimAPIResponse + if err := json.Unmarshal(body, &results); err != nil || len(results) == 0 { + n.cacheNegative(cacheKey) + return NominatimResult{}, false + } + + r := results[0] + lat, errLat := strconv.ParseFloat(r.Lat, 64) + lng, errLng := strconv.ParseFloat(r.Lon, 64) + if errLat != nil || errLng != nil { + n.cacheNegative(cacheKey) + return NominatimResult{}, false + } + + result := NominatimResult{ + Lat: lat, + Lng: lng, + CountryCode: strings.ToUpper(r.Address.CountryCode), + DisplayName: r.DisplayName, + } + + n.cacheMu.Lock() + n.cache[cacheKey] = &nominatimCacheEntry{result: result, ok: true} + n.cacheMu.Unlock() + + return result, true +} + +func (n *NominatimClient) cacheNegative(key string) { + n.cacheMu.Lock() + n.cache[key] = &nominatimCacheEntry{ok: false} + n.cacheMu.Unlock() +} + +// CacheStats returns the number of cached entries (for diagnostics). +func (n *NominatimClient) CacheStats() (total int, hits int) { + n.cacheMu.RLock() + defer n.cacheMu.RUnlock() + total = len(n.cache) + for _, e := range n.cache { + if e.ok { + hits++ + } + } + return total, hits +} + diff --git a/internal/collector/normalize/geocoder.go b/internal/collector/normalize/geocoder.go new file mode 100644 index 0000000..360f0aa --- /dev/null +++ b/internal/collector/normalize/geocoder.go @@ -0,0 +1,282 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package normalize + +import ( + "context" + "regexp" + "strings" + "unicode" +) + +// CityLookup abstracts the city database so normalize doesn't import sourcedb. +type CityLookup interface { + LookupCity(ctx context.Context, name string, countryCode string) (CityLookupResult, bool) +} + +// CityLookupResult mirrors sourcedb.CityResult without creating a dependency. +type CityLookupResult struct { + Name string + CountryCode string + Lat float64 + Lng float64 + Population int +} + +// GeoResult is the output of the full geocoding pipeline. +type GeoResult struct { + Lat float64 + Lng float64 + CountryCode string + CityName string + Source string // "city-db", "nominatim", "country-text", "capital", "registry" +} + +// Geocoder chains the three geocoding tiers: +// 1. City gazetteer (GeoNames in SQLite) — fast, local, city-level precision +// 2. Nominatim (OSM) — external fallback for place names not in the DB +// 3. Country-level (text scanning + capital coords) — always available +type Geocoder struct { + cities CityLookup // may be nil + nominatim *NominatimClient // may be nil +} + +// NewGeocoder creates a geocoder. Both deps are optional — pass nil to skip. +func NewGeocoder(cities CityLookup, nominatim *NominatimClient) *Geocoder { + return &Geocoder{cities: cities, nominatim: nominatim} +} + +// wordBoundaryRe matches sequences of word characters for tokenizing text +// into potential city name candidates. +var wordBoundaryRe = regexp.MustCompile(`[\p{L}\p{N}][\p{L}\p{N}\s'-]{2,30}`) + +// Resolve geocodes a text string (typically alert title + summary) to +// the most precise coordinates available. countryHint is the source's +// country code (e.g. "DE") and helps disambiguate city names. +func (g *Geocoder) Resolve(ctx context.Context, text string, countryHint string) GeoResult { + countryHint = strings.ToUpper(strings.TrimSpace(countryHint)) + + // ── Tier 1: City gazetteer ────────────────────────────────── + if g.cities != nil { + if result, ok := g.matchCityInText(ctx, text, countryHint); ok { + return result + } + } + + // ── Tier 2: Nominatim for extracted place-like tokens ─────── + if g.nominatim != nil { + if result, ok := g.nominatimFromText(ctx, text, countryHint); ok { + return result + } + } + + // ── Tier 3: Country-level from text ───────────────────────── + if lat, lng, code, ok := geocodeText(text); ok { + // Use capital coords instead of centroid. + if capital, cok := capitalCoords[code]; cok { + return GeoResult{Lat: capital[0], Lng: capital[1], CountryCode: code, Source: "capital"} + } + return GeoResult{Lat: lat, Lng: lng, CountryCode: code, Source: "country-text"} + } + + // ── Fallback: use country hint's capital ──────────────────── + if countryHint != "" && countryHint != "INT" { + if capital, ok := capitalCoords[countryHint]; ok { + return GeoResult{Lat: capital[0], Lng: capital[1], CountryCode: countryHint, Source: "capital"} + } + } + + return GeoResult{} // no match +} + +// matchCityInText extracts candidate n-grams from text and looks them up +// in the city database. Returns the match with the highest population that +// appears rightmost in the text (consistent with geocodeText strategy). +func (g *Geocoder) matchCityInText(ctx context.Context, text string, countryHint string) (GeoResult, bool) { + candidates := extractCandidateNames(text) + if len(candidates) == 0 { + return GeoResult{}, false + } + + type hit struct { + pos int + pop int + name string + lat float64 + lng float64 + code string + } + var best *hit + + for _, c := range candidates { + result, ok := g.cities.LookupCity(ctx, c.name, countryHint) + if !ok { + continue + } + // Skip tiny places (pop < 5000) unless they match country hint. + if result.Population < 5000 && result.CountryCode != countryHint { + continue + } + h := hit{ + pos: c.endPos, + pop: result.Population, + name: result.Name, + lat: result.Lat, + lng: result.Lng, + code: result.CountryCode, + } + if best == nil || + h.pos > best.pos || + (h.pos == best.pos && h.pop > best.pop) { + best = &h + } + } + + if best != nil { + return GeoResult{ + Lat: best.lat, + Lng: best.lng, + CountryCode: best.code, + CityName: best.name, + Source: "city-db", + }, true + } + return GeoResult{}, false +} + +type nameCandidate struct { + name string + endPos int +} + +// extractCandidateNames pulls potential place names from text. It extracts +// capitalized word sequences (1-4 words) which is how city names typically +// appear in headlines. E.g. "Explosion in San Francisco kills 3" → +// ["Explosion", "San Francisco", "San Francisco kills"]. +func extractCandidateNames(text string) []nameCandidate { + words := tokenizeWords(text) + if len(words) == 0 { + return nil + } + + var candidates []nameCandidate + seen := map[string]struct{}{} + + // Single words and multi-word sequences (up to 4 words). + for i := range words { + for n := 1; n <= 4 && i+n <= len(words); n++ { + var parts []string + allEmpty := true + for j := i; j < i+n; j++ { + w := words[j] + if w.text == "" { + break + } + allEmpty = false + parts = append(parts, w.text) + } + if allEmpty || len(parts) != n { + break + } + name := strings.Join(parts, " ") + lower := strings.ToLower(name) + + // Skip very short single words and common noise. + if n == 1 && len(name) < 3 { + continue + } + if isGeoStopword(lower) { + continue + } + + if _, ok := seen[lower]; ok { + continue + } + seen[lower] = struct{}{} + candidates = append(candidates, nameCandidate{ + name: name, + endPos: words[i+n-1].endPos, + }) + } + } + return candidates +} + +type wordToken struct { + text string + endPos int +} + +func tokenizeWords(text string) []wordToken { + var tokens []wordToken + inWord := false + start := 0 + for i, r := range text { + if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '\'' || r == '-' || r == '.' { + if !inWord { + start = i + inWord = true + } + } else { + if inWord { + tokens = append(tokens, wordToken{text: text[start:i], endPos: i}) + inWord = false + } + } + } + if inWord { + tokens = append(tokens, wordToken{text: text[start:], endPos: len(text)}) + } + return tokens +} + +var geoStopwords = map[string]bool{ + // Common English words that are also city/place names but are almost + // never geographic references in OSINT headlines. + "the": true, "and": true, "for": true, "new": true, "has": true, + "was": true, "are": true, "with": true, "from": true, "that": true, + "this": true, "not": true, "but": true, "all": true, "its": true, + "will": true, "can": true, "more": true, "update": true, "alert": true, + "warning": true, "report": true, "press": true, "release": true, + "security": true, "advisory": true, "notice": true, "bulletin": true, + "critical": true, "high": true, "medium": true, "low": true, "info": true, +} + +func isGeoStopword(lower string) bool { + return geoStopwords[lower] +} + +// nominatimFromText tries Nominatim for capitalized multi-word tokens that +// look like place names. Only attempts a few lookups to stay within rate limits. +func (g *Geocoder) nominatimFromText(ctx context.Context, text string, countryHint string) (GeoResult, bool) { + candidates := extractCandidateNames(text) + if len(candidates) == 0 { + return GeoResult{}, false + } + + // Only try the last few candidates (rightmost = most likely geographic). + maxAttempts := 3 + start := len(candidates) - maxAttempts + if start < 0 { + start = 0 + } + + for i := len(candidates) - 1; i >= start; i-- { + c := candidates[i] + if len(c.name) < 4 { + continue + } + result, ok := g.nominatim.Geocode(ctx, c.name, countryHint) + if ok { + return GeoResult{ + Lat: result.Lat, + Lng: result.Lng, + CountryCode: result.CountryCode, + CityName: c.name, + Source: "nominatim", + }, true + } + } + return GeoResult{}, false +} diff --git a/internal/collector/normalize/geocoder_test.go b/internal/collector/normalize/geocoder_test.go new file mode 100644 index 0000000..14532ad --- /dev/null +++ b/internal/collector/normalize/geocoder_test.go @@ -0,0 +1,176 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package normalize + +import ( + "context" + "testing" +) + +// mockCityLookup is a simple in-memory mock for testing. +type mockCityLookup struct { + cities map[string]CityLookupResult +} + +func (m *mockCityLookup) LookupCity(_ context.Context, name string, countryCode string) (CityLookupResult, bool) { + key := name + if countryCode != "" { + // Try country-specific first. + if r, ok := m.cities[name+"|"+countryCode]; ok { + return r, true + } + } + r, ok := m.cities[key] + return r, ok +} + +func newMockCities() *mockCityLookup { + return &mockCityLookup{cities: map[string]CityLookupResult{ + "Valletta": {Name: "Valletta", CountryCode: "MT", Lat: 35.90, Lng: 14.51, Population: 6400}, + "Berlin": {Name: "Berlin", CountryCode: "DE", Lat: 52.52, Lng: 13.41, Population: 3700000}, + "Munich": {Name: "Munich", CountryCode: "DE", Lat: 48.14, Lng: 11.58, Population: 1500000}, + "Kyiv": {Name: "Kyiv", CountryCode: "UA", Lat: 50.45, Lng: 30.52, Population: 3000000}, + "Mogadishu": {Name: "Mogadishu", CountryCode: "SO", Lat: 2.05, Lng: 45.32, Population: 2900000}, + "Aleppo": {Name: "Aleppo", CountryCode: "SY", Lat: 36.20, Lng: 37.17, Population: 1800000}, + }} +} + +func TestGeocoderResolve_CityDB(t *testing.T) { + g := NewGeocoder(newMockCities(), nil) + + tests := []struct { + name string + text string + countryHint string + wantCity string + wantCode string + wantSource string + }{ + { + name: "city in headline", + text: "Explosion rocks central Berlin district", + wantCity: "Berlin", + wantCode: "DE", + wantSource: "city-db", + }, + { + name: "city with country hint", + text: "Air raid sirens in Kyiv as strikes continue", + countryHint: "UA", + wantCity: "Kyiv", + wantCode: "UA", + wantSource: "city-db", + }, + { + name: "rightmost city wins", + text: "Berlin conference discusses Aleppo humanitarian crisis", + wantCity: "Aleppo", + wantCode: "SY", + wantSource: "city-db", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := g.Resolve(context.Background(), tt.text, tt.countryHint) + if result.CityName != tt.wantCity { + t.Errorf("CityName = %q, want %q", result.CityName, tt.wantCity) + } + if result.CountryCode != tt.wantCode { + t.Errorf("CountryCode = %q, want %q", result.CountryCode, tt.wantCode) + } + if result.Source != tt.wantSource { + t.Errorf("Source = %q, want %q", result.Source, tt.wantSource) + } + }) + } +} + +func TestGeocoderResolve_FallbackToCapital(t *testing.T) { + // No city DB, no Nominatim — should fall back to country text + capitals. + g := NewGeocoder(nil, nil) + + result := g.Resolve(context.Background(), "Somalia conflict escalates", "") + if result.CountryCode != "SO" { + t.Errorf("CountryCode = %q, want SO", result.CountryCode) + } + // Should use capital coords (Mogadishu) not centroid. + if result.Source != "capital" { + t.Errorf("Source = %q, want capital", result.Source) + } + if result.Lat < 1.5 || result.Lat > 3.0 { + t.Errorf("Lat = %f, want ~2.05 (Mogadishu)", result.Lat) + } +} + +func TestGeocoderResolve_CountryHintCapital(t *testing.T) { + // No city DB, no text match — should use country hint's capital. + g := NewGeocoder(nil, nil) + + result := g.Resolve(context.Background(), "New advisory issued for financial sector", "MT") + if result.Source != "capital" { + t.Errorf("Source = %q, want capital", result.Source) + } + // Valletta coordinates. + if result.Lat < 35.5 || result.Lat > 36.5 { + t.Errorf("Lat = %f, want ~35.90 (Valletta)", result.Lat) + } +} + +func TestCapitalCoords_IslandsOnLand(t *testing.T) { + // Verify that island nations have capital coords on land. + islands := map[string]string{ + "MT": "Valletta", + "CY": "Nicosia", + "SG": "Singapore", + "JM": "Kingston", + "CU": "Havana", + "IS": "Reykjavik", + } + + for code, name := range islands { + coords, ok := capitalCoords[code] + if !ok { + t.Errorf("missing capital coords for %s (%s)", code, name) + continue + } + // Sanity: lat/lng should be non-zero. + if coords[0] == 0 && coords[1] == 0 { + t.Errorf("capital coords for %s (%s) are zero", code, name) + } + } +} + +func TestGeocodeCountryCode_UsesCapitals(t *testing.T) { + // Malta centroid is in the sea. Capital (Valletta) should be returned. + lat, lng, name, ok := geocodeCountryCode("MT") + if !ok { + // MT might not be in geoCountries — that's fine for this test. + t.Skip("MT not in geoCountries") + } + _ = name + // Valletta is at 35.90, 14.51. Centroid would be different. + if lat < 35.5 || lat > 36.5 || lng < 14.0 || lng > 15.0 { + t.Errorf("geocodeCountryCode(MT) = (%f, %f), want Valletta area", lat, lng) + } +} + +func TestExtractCandidateNames(t *testing.T) { + candidates := extractCandidateNames("Explosion in San Francisco kills 3 near Mission District") + + names := make(map[string]bool) + for _, c := range candidates { + names[c.name] = true + } + + if !names["San"] { + t.Error("expected 'San' in candidates") + } + if !names["San Francisco"] { + t.Error("expected 'San Francisco' in candidates") + } + if !names["Mission District"] { + t.Error("expected 'Mission District' in candidates") + } +} diff --git a/internal/collector/normalize/normalize.go b/internal/collector/normalize/normalize.go index 45d8933..ba89b36 100644 --- a/internal/collector/normalize/normalize.go +++ b/internal/collector/normalize/normalize.go @@ -4,6 +4,7 @@ package normalize import ( + "context" "crypto/sha1" "encoding/hex" "math" @@ -124,8 +125,9 @@ var ( ) type Context struct { - Config config.Config - Now time.Time + Config config.Config + Now time.Time + Geocoder *Geocoder // optional; nil falls back to country-level only } type FeedContext struct { @@ -318,16 +320,45 @@ func baseAlert(ctx Context, meta model.RegistrySource, title string, link string baseLat, baseLng := meta.Lat, meta.Lng source := meta.Source + // Use capital coords instead of geographic centroid for the source's + // country — fixes islands (Malta, Cyprus, etc.) landing in the sea. + if source.CountryCode != "" && source.CountryCode != "INT" { + if capital, ok := capitalCoords[source.CountryCode]; ok { + baseLat, baseLng = capital[0], capital[1] + } + } + + geocoded := false + // For international sources, try to geocode the alert to the actual // crisis location instead of pinning it to the org's HQ. if meta.RegionTag == "INT" || meta.Source.CountryCode == "INT" { - if gLat, gLng, code, ok := geocodeText(title); ok { - baseLat, baseLng = gLat, gLng - if name := countryNameFromCode(code); name != "" { - source.Country = name - source.CountryCode = code + if ctx.Geocoder != nil { + // Enhanced geocoding: city DB → Nominatim → country text. + if result := ctx.Geocoder.Resolve(context.Background(), title, ""); result.CountryCode != "" { + baseLat, baseLng = result.Lat, result.Lng + geocoded = true + if name := countryNameFromCode(result.CountryCode); name != "" { + source.Country = name + source.CountryCode = result.CountryCode + } } } + if !geocoded { + if gLat, gLng, code, ok := geocodeText(title); ok { + baseLat, baseLng = gLat, gLng + if name := countryNameFromCode(code); name != "" { + source.Country = name + source.CountryCode = code + } + } + } + } else if ctx.Geocoder != nil { + // Non-international source: try city-level geocoding within the + // source's country for better pin placement. + if result := ctx.Geocoder.Resolve(context.Background(), title, source.CountryCode); result.Source == "city-db" || result.Source == "nominatim" { + baseLat, baseLng = result.Lat, result.Lng + } } lat, lng := jitter(baseLat, baseLng, meta.Source.SourceID+":"+link) diff --git a/internal/collector/run/run.go b/internal/collector/run/run.go index c7992ae..9a45974 100644 --- a/internal/collector/run/run.go +++ b/internal/collector/run/run.go @@ -99,7 +99,8 @@ func (r Runner) runOnce(ctx context.Context, cfg config.Config) error { } now := time.Now().UTC() - nctx := normalize.Context{Config: cfg, Now: now} + geocoder := r.initGeocoder(ctx, cfg) + nctx := normalize.Context{Config: cfg, Now: now, Geocoder: geocoder} categoryDictionary, err := dictionary.Load(cfg.CategoryDictionaryPath) if err != nil { fmt.Fprintf(r.stderr, "WARN category dictionary load failed (falling back to legacy filters): %v\n", err) @@ -785,6 +786,62 @@ func (r Runner) mergeRegistry(ctx context.Context, cfg config.Config) error { return db.MergeRegistry(ctx, cfg.RegistrySeedPath) } +// cityLookupAdapter wraps sourcedb.DB to satisfy normalize.CityLookup. +type cityLookupAdapter struct { + db *sourcedb.DB +} + +func (a *cityLookupAdapter) LookupCity(ctx context.Context, name string, countryCode string) (normalize.CityLookupResult, bool) { + r, ok := a.db.LookupCity(ctx, name, countryCode) + if !ok { + return normalize.CityLookupResult{}, false + } + return normalize.CityLookupResult{ + Name: r.Name, + CountryCode: r.CountryCode, + Lat: r.Lat, + Lng: r.Lng, + Population: r.Population, + }, true +} + +func (r Runner) initGeocoder(ctx context.Context, cfg config.Config) *normalize.Geocoder { + var cities normalize.CityLookup + var nominatim *normalize.NominatimClient + + // Try to open the source DB for city lookups. + if isSQLitePath(cfg.RegistryPath) { + db, err := sourcedb.Open(cfg.RegistryPath) + if err == nil { + // Import GeoNames if the cities table is empty and the file exists. + if !db.HasCities(ctx) && cfg.GeoNamesPath != "" { + if err := db.ImportGeoNames(ctx, cfg.GeoNamesPath); err != nil { + fmt.Fprintf(r.stderr, "WARN geonames import: %v\n", err) + } + } + if db.HasCities(ctx) { + cities = &cityLookupAdapter{db: db} + // NOTE: we intentionally don't defer db.Close() here because + // the geocoder is used throughout the run. The DB handle is + // safe for concurrent reads. + } else { + db.Close() + } + } else { + fmt.Fprintf(r.stderr, "WARN geocoder DB open: %v\n", err) + } + } + + if cfg.NominatimEnabled { + nominatim = normalize.NewNominatimClient(cfg.NominatimBaseURL, cfg.WikimediaUserAgent) + } + + if cities == nil && nominatim == nil { + return nil + } + return normalize.NewGeocoder(cities, nominatim) +} + func (r Runner) runDiscoveryLoop(ctx context.Context, cfg config.Config) { runOnce := func() { if err := discover.Run(ctx, cfg, r.stdout, r.stderr); err != nil && ctx.Err() == nil { diff --git a/internal/sourcedb/geocode.go b/internal/sourcedb/geocode.go new file mode 100644 index 0000000..26c3a00 --- /dev/null +++ b/internal/sourcedb/geocode.go @@ -0,0 +1,164 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package sourcedb + +import ( + "bufio" + "context" + "fmt" + "os" + "strconv" + "strings" +) + +// CityResult is a geocoded city from the GeoNames gazetteer. +type CityResult struct { + Name string + CountryCode string + Lat float64 + Lng float64 + Population int +} + +// ImportGeoNames loads a GeoNames cities500.txt (tab-separated) file into +// the cities table. It replaces all existing rows. The file format is +// documented at https://download.geonames.org/export/dump/readme.txt. +// +// Columns used: 0=geonameid, 1=name, 2=asciiname, 4=latitude, 5=longitude, +// 8=country_code, 14=population. +func (db *DB) ImportGeoNames(ctx context.Context, path string) error { + f, err := os.Open(path) + if err != nil { + return fmt.Errorf("open geonames file: %w", err) + } + defer f.Close() + + tx, err := db.sql.BeginTx(ctx, nil) + if err != nil { + return fmt.Errorf("begin geonames import tx: %w", err) + } + defer tx.Rollback() //nolint:errcheck + + if _, err := tx.ExecContext(ctx, `DELETE FROM cities`); err != nil { + return fmt.Errorf("clear cities table: %w", err) + } + + stmt, err := tx.PrepareContext(ctx, + `INSERT INTO cities (id, name, name_lower, ascii_name, ascii_lower, country_code, lat, lng, population) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`) + if err != nil { + return fmt.Errorf("prepare cities insert: %w", err) + } + defer stmt.Close() + + scanner := bufio.NewScanner(f) + scanner.Buffer(make([]byte, 0, 1024*1024), 1024*1024) + + var count int + for scanner.Scan() { + fields := strings.Split(scanner.Text(), "\t") + if len(fields) < 15 { + continue + } + geoID, _ := strconv.Atoi(fields[0]) + name := strings.TrimSpace(fields[1]) + asciiName := strings.TrimSpace(fields[2]) + lat, _ := strconv.ParseFloat(fields[4], 64) + lng, _ := strconv.ParseFloat(fields[5], 64) + cc := strings.TrimSpace(fields[8]) + pop, _ := strconv.Atoi(fields[14]) + + if name == "" || cc == "" { + continue + } + + if _, err := stmt.ExecContext(ctx, geoID, name, strings.ToLower(name), asciiName, strings.ToLower(asciiName), cc, lat, lng, pop); err != nil { + return fmt.Errorf("insert city %q: %w", name, err) + } + count++ + } + if err := scanner.Err(); err != nil { + return fmt.Errorf("scan geonames file: %w", err) + } + + if err := tx.Commit(); err != nil { + return fmt.Errorf("commit geonames import: %w", err) + } + fmt.Printf("Imported %d cities from GeoNames\n", count) + return nil +} + +// HasCities returns true if the cities table is populated. +func (db *DB) HasCities(ctx context.Context) bool { + var count int + if err := db.sql.QueryRowContext(ctx, `SELECT COUNT(*) FROM cities LIMIT 1`).Scan(&count); err != nil { + return false + } + return count > 0 +} + +// LookupCity finds the largest city matching the given name. If countryCode +// is non-empty, results for that country are strongly preferred. +func (db *DB) LookupCity(ctx context.Context, name string, countryCode string) (CityResult, bool) { + nameLower := strings.ToLower(strings.TrimSpace(name)) + countryCode = strings.ToUpper(strings.TrimSpace(countryCode)) + + if nameLower == "" { + return CityResult{}, false + } + + // Try country-specific match first. + if countryCode != "" { + var r CityResult + err := db.sql.QueryRowContext(ctx, + `SELECT name, country_code, lat, lng, population FROM cities + WHERE (name_lower = ? OR ascii_lower = ?) AND country_code = ? + ORDER BY population DESC LIMIT 1`, + nameLower, nameLower, countryCode).Scan(&r.Name, &r.CountryCode, &r.Lat, &r.Lng, &r.Population) + if err == nil { + return r, true + } + } + + // Fallback: largest city worldwide with that name. + var r CityResult + err := db.sql.QueryRowContext(ctx, + `SELECT name, country_code, lat, lng, population FROM cities + WHERE name_lower = ? OR ascii_lower = ? + ORDER BY population DESC LIMIT 1`, + nameLower, nameLower).Scan(&r.Name, &r.CountryCode, &r.Lat, &r.Lng, &r.Population) + if err == nil { + return r, true + } + return CityResult{}, false +} + +// LookupCities finds all cities matching the given name, ordered by +// population descending. Used for batch scanning of text. +func (db *DB) LookupCities(ctx context.Context, name string) ([]CityResult, error) { + nameLower := strings.ToLower(strings.TrimSpace(name)) + if nameLower == "" { + return nil, nil + } + + rows, err := db.sql.QueryContext(ctx, + `SELECT name, country_code, lat, lng, population FROM cities + WHERE name_lower = ? OR ascii_lower = ? + ORDER BY population DESC LIMIT 10`, + nameLower, nameLower) + if err != nil { + return nil, err + } + defer rows.Close() + + var results []CityResult + for rows.Next() { + var r CityResult + if err := rows.Scan(&r.Name, &r.CountryCode, &r.Lat, &r.Lng, &r.Population); err != nil { + continue + } + results = append(results, r) + } + return results, rows.Err() +} diff --git a/internal/sourcedb/schema.sql b/internal/sourcedb/schema.sql index 47bc4db..b766cc5 100644 --- a/internal/sourcedb/schema.sql +++ b/internal/sourcedb/schema.sql @@ -149,6 +149,21 @@ CREATE INDEX IF NOT EXISTS idx_agency_category_coverage_category ON agency_categ CREATE INDEX IF NOT EXISTS idx_alerts_status ON alerts(status); CREATE INDEX IF NOT EXISTS idx_alerts_source_id ON alerts(source_id); +CREATE TABLE IF NOT EXISTS cities ( + id INTEGER PRIMARY KEY, + name TEXT NOT NULL, + name_lower TEXT NOT NULL, + ascii_name TEXT NOT NULL, + ascii_lower TEXT NOT NULL, + country_code TEXT NOT NULL, + lat REAL NOT NULL, + lng REAL NOT NULL, + population INTEGER NOT NULL DEFAULT 0 +); +CREATE INDEX IF NOT EXISTS idx_cities_name_lower ON cities(name_lower); +CREATE INDEX IF NOT EXISTS idx_cities_ascii_lower ON cities(ascii_lower); +CREATE INDEX IF NOT EXISTS idx_cities_country_code ON cities(country_code); + CREATE VIRTUAL TABLE IF NOT EXISTS agencies_fts USING fts5( agency_id UNINDEXED, authority_name, From c42dad2c078f435c5df3fdf61aeaa5a896296a1c Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Tue, 17 Mar 2026 08:20:24 +0100 Subject: [PATCH 42/58] feat: auto-discover missing country feeds via gap analysis MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gap analysis scans the active registry against 120+ target countries worldwide. Missing country+category combinations generate synthetic search candidates that feed into the existing LLM search + RSS probe pipeline. Covers Europe, Americas, Asia-Pacific, Middle East, Africa, Central Asia, and Caucasus. Also fixes Interpol notice URLs: 2026/5314 → 2026-5314 in fragment. --- internal/collector/discover/discover.go | 14 +- internal/collector/discover/gap.go | 310 ++++++++++++++++++++++++ internal/collector/discover/gap_test.go | 68 ++++++ internal/collector/run/run.go | 8 +- 4 files changed, 395 insertions(+), 5 deletions(-) create mode 100644 internal/collector/discover/gap.go create mode 100644 internal/collector/discover/gap_test.go diff --git a/internal/collector/discover/discover.go b/internal/collector/discover/discover.go index 014fada..d41a168 100644 --- a/internal/collector/discover/discover.go +++ b/internal/collector/discover/discover.go @@ -53,9 +53,11 @@ func Run(ctx context.Context, cfg config.Config, stdout io.Writer, stderr io.Wri searchClient = vet.NewClient(cfg) } - // Load existing registry for deduplication. + // Load existing registry for deduplication and gap analysis. existing := map[string]struct{}{} + var registrySources []model.RegistrySource if sources, err := registry.Load(cfg.RegistryPath); err == nil { + registrySources = sources for _, src := range sources { if src.FeedURL != "" { existing[normalizeURL(src.FeedURL)] = struct{}{} @@ -71,7 +73,7 @@ func Run(ctx context.Context, cfg config.Config, stdout io.Writer, stderr io.Wri var discovered []DiscoveredSource dead := loadDeadLetterQueue(cfg.ReplacementQueuePath) fmt.Fprintf(stderr, "Dead-letter queue: %d sources will be skipped\n", len(dead)) - seededCandidates, err := generateAutonomousCandidates(ctx, cfg, client, searchClient, dead, stderr) + seededCandidates, err := generateAutonomousCandidates(ctx, cfg, client, searchClient, dead, registrySources, stderr) if err != nil { fmt.Fprintf(stderr, "WARN autonomous candidate discovery failed: %v\n", err) } @@ -180,7 +182,7 @@ func Run(ctx context.Context, cfg config.Config, stdout io.Writer, stderr io.Wri return nil } -func generateAutonomousCandidates(ctx context.Context, cfg config.Config, client *fetch.Client, searchClient searchCompleter, dead []model.SourceReplacementCandidate, stderr io.Writer) ([]model.SourceCandidate, error) { +func generateAutonomousCandidates(ctx context.Context, cfg config.Config, client *fetch.Client, searchClient searchCompleter, dead []model.SourceReplacementCandidate, registrySources []model.RegistrySource, stderr io.Writer) ([]model.SourceCandidate, error) { candidates := make([]model.SourceCandidate, 0) var failures []string var slowSkips []string @@ -265,6 +267,12 @@ func generateAutonomousCandidates(ctx context.Context, cfg config.Config, client if len(slowSkips) > 0 { fmt.Fprintf(stderr, "Structured discovery skipped slow providers: %s\n", strings.Join(slowSkips, ", ")) } + // Gap analysis: find countries with missing categories and seed searches. + gapCandidates := AnalyzeGaps(registrySources, stderr) + if len(gapCandidates) > 0 { + candidates = append(candidates, gapCandidates...) + } + searchSeeds := append([]model.SourceCandidate{}, candidates...) replacementTargets := buildReplacementSearchTargets(dead) if len(replacementTargets) > 0 { diff --git a/internal/collector/discover/gap.go b/internal/collector/discover/gap.go new file mode 100644 index 0000000..4938952 --- /dev/null +++ b/internal/collector/discover/gap.go @@ -0,0 +1,310 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package discover + +import ( + "fmt" + "io" + "strings" + + "github.com/scalytics/euosint/internal/collector/model" +) + +// gapTarget defines a country and the minimum categories it should have. +type gapTarget struct { + Country string + CountryCode string + Categories []string +} + +// coreCategories is the minimum set of feed categories every country should have. +var coreCategories = []string{ + "cyber_advisory", + "public_appeal", +} + +// expandedCategories adds intel, travel, and fraud for countries where these +// are commonly published by government agencies. +var expandedCategories = []string{ + "cyber_advisory", + "public_appeal", + "travel_warning", + "intelligence_report", + "fraud_alert", +} + +// targetCountries lists all countries the system should cover with at least +// core categories. European/Nordic countries use the expanded set. +var targetCountries = []gapTarget{ + // ─── Nordics ──────────────────────────────────────────────── + {"Norway", "NO", expandedCategories}, + {"Sweden", "SE", expandedCategories}, + {"Finland", "FI", expandedCategories}, + {"Denmark", "DK", expandedCategories}, + {"Iceland", "IS", coreCategories}, + + // ─── Western Europe ───────────────────────────────────────── + {"United Kingdom", "GB", expandedCategories}, + {"France", "FR", expandedCategories}, + {"Germany", "DE", expandedCategories}, + {"Netherlands", "NL", expandedCategories}, + {"Belgium", "BE", expandedCategories}, + {"Luxembourg", "LU", coreCategories}, + {"Ireland", "IE", expandedCategories}, + {"Switzerland", "CH", expandedCategories}, + {"Austria", "AT", expandedCategories}, + + // ─── Southern Europe ──────────────────────────────────────── + {"Spain", "ES", expandedCategories}, + {"Portugal", "PT", expandedCategories}, + {"Italy", "IT", expandedCategories}, + {"Greece", "GR", expandedCategories}, + {"Malta", "MT", coreCategories}, + {"Cyprus", "CY", coreCategories}, + + // ─── Eastern Europe ───────────────────────────────────────── + {"Poland", "PL", expandedCategories}, + {"Czech Republic", "CZ", expandedCategories}, + {"Slovakia", "SK", coreCategories}, + {"Hungary", "HU", coreCategories}, + {"Romania", "RO", expandedCategories}, + {"Bulgaria", "BG", coreCategories}, + {"Croatia", "HR", coreCategories}, + {"Slovenia", "SI", coreCategories}, + {"Serbia", "RS", coreCategories}, + {"Bosnia", "BA", coreCategories}, + {"Montenegro", "ME", coreCategories}, + {"North Macedonia", "MK", coreCategories}, + {"Albania", "AL", coreCategories}, + {"Kosovo", "XK", coreCategories}, + {"Moldova", "MD", coreCategories}, + + // ─── Baltics ──────────────────────────────────────────────── + {"Estonia", "EE", expandedCategories}, + {"Latvia", "LV", expandedCategories}, + {"Lithuania", "LT", expandedCategories}, + + // ─── East ─────────────────────────────────────────────────── + {"Ukraine", "UA", expandedCategories}, + {"Georgia", "GE", coreCategories}, + {"Turkey", "TR", expandedCategories}, + + // ─── Americas ─────────────────────────────────────────────── + {"United States", "US", expandedCategories}, + {"Canada", "CA", expandedCategories}, + {"Mexico", "MX", expandedCategories}, + {"Brazil", "BR", expandedCategories}, + {"Argentina", "AR", expandedCategories}, + {"Colombia", "CO", coreCategories}, + {"Chile", "CL", coreCategories}, + {"Peru", "PE", coreCategories}, + {"Ecuador", "EC", coreCategories}, + {"Venezuela", "VE", coreCategories}, + {"Cuba", "CU", coreCategories}, + {"Panama", "PA", coreCategories}, + {"Costa Rica", "CR", coreCategories}, + {"Guatemala", "GT", coreCategories}, + {"Honduras", "HN", coreCategories}, + {"El Salvador", "SV", coreCategories}, + {"Nicaragua", "NI", coreCategories}, + {"Dominican Republic", "DO", coreCategories}, + {"Jamaica", "JM", coreCategories}, + {"Haiti", "HT", coreCategories}, + {"Paraguay", "PY", coreCategories}, + {"Uruguay", "UY", coreCategories}, + {"Bolivia", "BO", coreCategories}, + + // ─── Asia-Pacific ─────────────────────────────────────────── + {"Japan", "JP", expandedCategories}, + {"South Korea", "KR", expandedCategories}, + {"China", "CN", expandedCategories}, + {"India", "IN", expandedCategories}, + {"Australia", "AU", expandedCategories}, + {"New Zealand", "NZ", coreCategories}, + {"Indonesia", "ID", expandedCategories}, + {"Malaysia", "MY", coreCategories}, + {"Singapore", "SG", expandedCategories}, + {"Thailand", "TH", coreCategories}, + {"Philippines", "PH", coreCategories}, + {"Vietnam", "VN", coreCategories}, + {"Taiwan", "TW", expandedCategories}, + {"Pakistan", "PK", coreCategories}, + {"Bangladesh", "BD", coreCategories}, + {"Sri Lanka", "LK", coreCategories}, + {"Nepal", "NP", coreCategories}, + {"Mongolia", "MN", coreCategories}, + {"Cambodia", "KH", coreCategories}, + {"Myanmar", "MM", coreCategories}, + {"Laos", "LA", coreCategories}, + + // ─── Middle East ──────────────────────────────────────────── + {"Israel", "IL", expandedCategories}, + {"Saudi Arabia", "SA", expandedCategories}, + {"United Arab Emirates", "AE", expandedCategories}, + {"Qatar", "QA", coreCategories}, + {"Kuwait", "KW", coreCategories}, + {"Bahrain", "BH", coreCategories}, + {"Oman", "OM", coreCategories}, + {"Jordan", "JO", coreCategories}, + {"Lebanon", "LB", coreCategories}, + {"Iraq", "IQ", coreCategories}, + {"Iran", "IR", expandedCategories}, + {"Syria", "SY", coreCategories}, + {"Yemen", "YE", coreCategories}, + {"Palestine", "PS", coreCategories}, + + // ─── Africa ───────────────────────────────────────────────── + {"South Africa", "ZA", expandedCategories}, + {"Nigeria", "NG", expandedCategories}, + {"Kenya", "KE", coreCategories}, + {"Egypt", "EG", expandedCategories}, + {"Morocco", "MA", coreCategories}, + {"Algeria", "DZ", coreCategories}, + {"Tunisia", "TN", coreCategories}, + {"Libya", "LY", coreCategories}, + {"Ethiopia", "ET", coreCategories}, + {"Ghana", "GH", coreCategories}, + {"Tanzania", "TZ", coreCategories}, + {"Uganda", "UG", coreCategories}, + {"Rwanda", "RW", coreCategories}, + {"Senegal", "SN", coreCategories}, + {"Ivory Coast", "CI", coreCategories}, + {"Cameroon", "CM", coreCategories}, + {"Congo", "CD", coreCategories}, + {"Mozambique", "MZ", coreCategories}, + {"Zimbabwe", "ZW", coreCategories}, + {"Zambia", "ZM", coreCategories}, + {"Mali", "ML", coreCategories}, + {"Burkina Faso", "BF", coreCategories}, + {"Niger", "NE", coreCategories}, + {"Chad", "TD", coreCategories}, + {"Sudan", "SD", coreCategories}, + {"South Sudan", "SS", coreCategories}, + {"Somalia", "SO", coreCategories}, + {"Eritrea", "ER", coreCategories}, + {"Madagascar", "MG", coreCategories}, + {"Angola", "AO", coreCategories}, + {"Namibia", "NA", coreCategories}, + {"Botswana", "BW", coreCategories}, + + // ─── Central Asia ─────────────────────────────────────────── + {"Kazakhstan", "KZ", coreCategories}, + {"Uzbekistan", "UZ", coreCategories}, + {"Kyrgyzstan", "KG", coreCategories}, + {"Tajikistan", "TJ", coreCategories}, + {"Turkmenistan", "TM", coreCategories}, + + // ─── Caucasus ─────────────────────────────────────────────── + {"Armenia", "AM", coreCategories}, + {"Azerbaijan", "AZ", coreCategories}, + + // ─── Russia / Belarus ─────────────────────────────────────── + {"Russia", "RU", expandedCategories}, + {"Belarus", "BY", coreCategories}, +} + +// gapCandidate is a synthetic search candidate generated by gap analysis. +type gapCandidate struct { + Country string + CountryCode string + Category string +} + +// AnalyzeGaps compares the active registry against target countries and +// returns synthetic candidates for missing country+category combinations. +func AnalyzeGaps(sources []model.RegistrySource, stderr io.Writer) []model.SourceCandidate { + // Build coverage map: country_code → set of categories with active feeds. + coverage := map[string]map[string]bool{} + for _, src := range sources { + cc := strings.ToUpper(src.Source.CountryCode) + if cc == "" || cc == "INT" { + continue + } + if coverage[cc] == nil { + coverage[cc] = map[string]bool{} + } + coverage[cc][src.Category] = true + } + + var gaps []gapCandidate + for _, target := range targetCountries { + covered := coverage[target.CountryCode] + for _, cat := range target.Categories { + if covered != nil && covered[cat] { + continue + } + gaps = append(gaps, gapCandidate{ + Country: target.Country, + CountryCode: target.CountryCode, + Category: cat, + }) + } + } + + if len(gaps) == 0 { + fmt.Fprintf(stderr, "Gap analysis: full coverage for all %d target countries\n", len(targetCountries)) + return nil + } + + fmt.Fprintf(stderr, "Gap analysis: found %d missing country+category combinations across %d target countries\n", len(gaps), countUniqueCountries(gaps)) + + // Convert gaps to search candidates with descriptive names. + candidates := make([]model.SourceCandidate, 0, len(gaps)) + for _, gap := range gaps { + candidates = append(candidates, model.SourceCandidate{ + AuthorityName: gapAuthorityLabel(gap.Country, gap.Category), + AuthorityType: gapAuthorityType(gap.Category), + Category: gap.Category, + Country: gap.Country, + CountryCode: gap.CountryCode, + Notes: "autonomous seed: gap-analysis", + }) + } + return candidates +} + +func countUniqueCountries(gaps []gapCandidate) int { + seen := map[string]bool{} + for _, g := range gaps { + seen[g.CountryCode] = true + } + return len(seen) +} + +// gapAuthorityLabel generates a descriptive search label for a gap. +func gapAuthorityLabel(country string, category string) string { + switch category { + case "cyber_advisory": + return country + " national CERT or CSIRT" + case "public_appeal": + return country + " national police" + case "travel_warning": + return country + " ministry of foreign affairs" + case "intelligence_report": + return country + " intelligence or security service" + case "fraud_alert": + return country + " financial regulator or central bank" + case "wanted_suspect": + return country + " wanted persons" + default: + return country + " " + strings.ReplaceAll(category, "_", " ") + } +} + +func gapAuthorityType(category string) string { + switch category { + case "cyber_advisory": + return "cert" + case "public_appeal", "wanted_suspect": + return "police" + case "travel_warning": + return "government" + case "intelligence_report": + return "national_security" + case "fraud_alert": + return "regulatory" + default: + return "government" + } +} diff --git a/internal/collector/discover/gap_test.go b/internal/collector/discover/gap_test.go new file mode 100644 index 0000000..9f5b41f --- /dev/null +++ b/internal/collector/discover/gap_test.go @@ -0,0 +1,68 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package discover + +import ( + "bytes" + "testing" + + "github.com/scalytics/euosint/internal/collector/model" +) + +func TestAnalyzeGaps_FindsMissing(t *testing.T) { + // A registry with only Germany cyber_advisory — everything else is a gap. + sources := []model.RegistrySource{ + {Category: "cyber_advisory", Source: model.SourceMetadata{CountryCode: "DE"}}, + {Category: "public_appeal", Source: model.SourceMetadata{CountryCode: "DE"}}, + {Category: "travel_warning", Source: model.SourceMetadata{CountryCode: "DE"}}, + {Category: "intelligence_report", Source: model.SourceMetadata{CountryCode: "DE"}}, + {Category: "fraud_alert", Source: model.SourceMetadata{CountryCode: "DE"}}, + } + + var buf bytes.Buffer + gaps := AnalyzeGaps(sources, &buf) + + if len(gaps) == 0 { + t.Fatal("expected gap candidates, got none") + } + + // Norway should be missing all categories. + norwayCats := map[string]bool{} + for _, g := range gaps { + if g.CountryCode == "NO" { + norwayCats[g.Category] = true + } + } + for _, cat := range expandedCategories { + if !norwayCats[cat] { + t.Errorf("expected Norway gap for %s", cat) + } + } + + // Germany should NOT appear (fully covered). + for _, g := range gaps { + if g.CountryCode == "DE" { + t.Errorf("unexpected gap for Germany: %s", g.Category) + } + } +} + +func TestAnalyzeGaps_FullCoverage(t *testing.T) { + // Build a registry that covers every target country+category. + var sources []model.RegistrySource + for _, target := range targetCountries { + for _, cat := range target.Categories { + sources = append(sources, model.RegistrySource{ + Category: cat, + Source: model.SourceMetadata{CountryCode: target.CountryCode}, + }) + } + } + + var buf bytes.Buffer + gaps := AnalyzeGaps(sources, &buf) + if len(gaps) != 0 { + t.Errorf("expected 0 gaps with full coverage, got %d", len(gaps)) + } +} diff --git a/internal/collector/run/run.go b/internal/collector/run/run.go index 9a45974..06175a8 100644 --- a/internal/collector/run/run.go +++ b/internal/collector/run/run.go @@ -507,20 +507,24 @@ func interpolBrowserURLs(sourceType string) (pageURL string, matchURL string) { func extractInterpolNoticeID(entityID string, link string) string { if id := strings.TrimSpace(entityID); id != "" { - return id + return strings.ReplaceAll(id, "/", "-") } parsed, err := url.Parse(strings.TrimSpace(link)) if err != nil { return "" } if fragment := strings.TrimSpace(parsed.Fragment); fragment != "" { - return fragment + return strings.ReplaceAll(fragment, "/", "-") } path := strings.Trim(parsed.Path, "/") if path == "" { return "" } + // API paths like /notices/v1/red/2026/5314 → "2026-5314" parts := strings.Split(path, "/") + if len(parts) >= 2 && parts[len(parts)-2] >= "1900" && parts[len(parts)-2] <= "2099" { + return parts[len(parts)-2] + "-" + parts[len(parts)-1] + } return strings.TrimSpace(parts[len(parts)-1]) } From ebbd5beb0450a92c8e2e8459bb39730242dff8fb Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Tue, 17 Mar 2026 08:28:06 +0100 Subject: [PATCH 43/58] feat: DDG headless browser search as primary discovery, LLM as fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DuckDuckGo search via headless Chrome is now the first-citizen feed discovery method — zero API keys, zero tokens. The system searches for RSS/Atom feeds using gap-analysis targets, extracts result URLs from DDG HTML, and feeds them into the existing probe pipeline. LLM search only runs for targets that DDG didn't cover, saving tokens. Also expanded feed probe paths with government/ministry patterns (DOJ-style feeds, multi-language /de/feed /fr/feed etc.) and enabled browser + DDG in docker-compose. --- docker-compose.yml | 3 + internal/collector/config/config.go | 9 + internal/collector/discover/discover.go | 52 +++- internal/collector/discover/probe.go | 25 ++ internal/collector/discover/search_ddg.go | 234 ++++++++++++++++++ .../collector/discover/search_ddg_test.go | 111 +++++++++ 6 files changed, 427 insertions(+), 7 deletions(-) create mode 100644 internal/collector/discover/search_ddg.go create mode 100644 internal/collector/discover/search_ddg_test.go diff --git a/docker-compose.yml b/docker-compose.yml index de75e03..842c4a3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -29,6 +29,9 @@ services: environment: GEONAMES_PATH: "/app/registry/cities500.txt" NOMINATIM_ENABLED: "1" + DDG_SEARCH_ENABLED: "1" + DDG_SEARCH_DELAY_MS: "8000" + BROWSER_ENABLED: "1" INTERVAL_MS: "900000" MAX_PER_SOURCE: "40" MISSING_PERSON_RELEVANCE_THRESHOLD: "0" diff --git a/internal/collector/config/config.go b/internal/collector/config/config.go index a532fc5..3483217 100644 --- a/internal/collector/config/config.go +++ b/internal/collector/config/config.go @@ -53,6 +53,9 @@ type Config struct { SearchDiscoveryEnabled bool SearchDiscoveryMaxTargets int SearchDiscoveryMaxURLsPerTarget int + DDGSearchEnabled bool + DDGSearchMaxQueries int + DDGSearchDelayMS int WikidataCachePath string WikidataCacheTTLHours int VettingEnabled bool @@ -113,6 +116,9 @@ func Default() Config { SearchDiscoveryEnabled: false, SearchDiscoveryMaxTargets: 4, SearchDiscoveryMaxURLsPerTarget: 3, + DDGSearchEnabled: true, + DDGSearchMaxQueries: 10, + DDGSearchDelayMS: 8000, WikidataCachePath: "registry/wikidata_cache", WikidataCacheTTLHours: 24, VettingEnabled: false, @@ -195,6 +201,9 @@ func FromEnv() Config { cfg.CuratedSeedPath = envString("CURATED_SEED_PATH", cfg.CuratedSeedPath) cfg.RegistrySeedPath = envString("REGISTRY_SEED_PATH", cfg.RegistrySeedPath) cfg.CursorsPath = envString("CURSORS_PATH", cfg.CursorsPath) + cfg.DDGSearchEnabled = envBool("DDG_SEARCH_ENABLED", cfg.DDGSearchEnabled) + cfg.DDGSearchMaxQueries = envInt("DDG_SEARCH_MAX_QUERIES", cfg.DDGSearchMaxQueries) + cfg.DDGSearchDelayMS = envInt("DDG_SEARCH_DELAY_MS", cfg.DDGSearchDelayMS) cfg.GeoNamesPath = envString("GEONAMES_PATH", cfg.GeoNamesPath) cfg.NominatimBaseURL = envString("NOMINATIM_BASE_URL", cfg.NominatimBaseURL) cfg.NominatimEnabled = envBool("NOMINATIM_ENABLED", cfg.NominatimEnabled) diff --git a/internal/collector/discover/discover.go b/internal/collector/discover/discover.go index d41a168..d147e73 100644 --- a/internal/collector/discover/discover.go +++ b/internal/collector/discover/discover.go @@ -46,12 +46,22 @@ func Run(ctx context.Context, cfg config.Config, stdout io.Writer, stderr io.Wri client := fetch.New(discoveryCfg) var searchClient *vet.Client var sourceVetter *vet.Vetter + var browser *fetch.BrowserClient if cfg.VettingEnabled { sourceVetter = vet.New(cfg) } if cfg.SearchDiscoveryEnabled { searchClient = vet.NewClient(cfg) } + if cfg.DDGSearchEnabled && cfg.BrowserEnabled { + b, err := fetch.NewBrowser(cfg.BrowserTimeoutMS) + if err != nil { + fmt.Fprintf(stderr, "WARN DDG search disabled (browser init failed): %v\n", err) + } else { + browser = b + defer browser.Close() + } + } // Load existing registry for deduplication and gap analysis. existing := map[string]struct{}{} @@ -73,7 +83,7 @@ func Run(ctx context.Context, cfg config.Config, stdout io.Writer, stderr io.Wri var discovered []DiscoveredSource dead := loadDeadLetterQueue(cfg.ReplacementQueuePath) fmt.Fprintf(stderr, "Dead-letter queue: %d sources will be skipped\n", len(dead)) - seededCandidates, err := generateAutonomousCandidates(ctx, cfg, client, searchClient, dead, registrySources, stderr) + seededCandidates, err := generateAutonomousCandidates(ctx, cfg, client, browser, searchClient, dead, registrySources, stderr) if err != nil { fmt.Fprintf(stderr, "WARN autonomous candidate discovery failed: %v\n", err) } @@ -182,7 +192,7 @@ func Run(ctx context.Context, cfg config.Config, stdout io.Writer, stderr io.Wri return nil } -func generateAutonomousCandidates(ctx context.Context, cfg config.Config, client *fetch.Client, searchClient searchCompleter, dead []model.SourceReplacementCandidate, registrySources []model.RegistrySource, stderr io.Writer) ([]model.SourceCandidate, error) { +func generateAutonomousCandidates(ctx context.Context, cfg config.Config, client *fetch.Client, browser *fetch.BrowserClient, searchClient searchCompleter, dead []model.SourceReplacementCandidate, registrySources []model.RegistrySource, stderr io.Writer) ([]model.SourceCandidate, error) { candidates := make([]model.SourceCandidate, 0) var failures []string var slowSkips []string @@ -279,12 +289,40 @@ func generateAutonomousCandidates(ctx context.Context, cfg config.Config, client fmt.Fprintf(stderr, "Replacement search targets: %d dead-source metadata entries queued for feed search\n", len(replacementTargets)) searchSeeds = append(searchSeeds, replacementTargets...) } - llmCandidates, err := llmSearchCandidates(ctx, cfg, searchClient, searchSeeds) + + // DDG search is the first citizen — free, no API key needed. + // LLM search is the fallback for targets DDG didn't cover. + ddgCandidates, err := ddgSearchCandidates(ctx, cfg, browser, searchSeeds) if err != nil { - failures = append(failures, fmt.Sprintf("llm-search: %v", err)) - } else if len(llmCandidates) > 0 { - fmt.Fprintf(stderr, "LLM search discovery: generated %d candidate URLs via %s\n", len(llmCandidates), cfg.VettingProvider) - candidates = append(candidates, llmCandidates...) + failures = append(failures, fmt.Sprintf("ddg-search: %v", err)) + } else if len(ddgCandidates) > 0 { + fmt.Fprintf(stderr, "DDG search discovery: found %d candidate URLs\n", len(ddgCandidates)) + candidates = append(candidates, ddgCandidates...) + } + + // LLM search only for remaining seeds that DDG didn't find results for. + if cfg.SearchDiscoveryEnabled && searchClient != nil { + ddgCoveredKeys := map[string]struct{}{} + for _, c := range ddgCandidates { + key := strings.ToLower(c.AuthorityName) + "|" + strings.ToUpper(c.CountryCode) + "|" + strings.ToLower(c.Category) + ddgCoveredKeys[key] = struct{}{} + } + var llmSeeds []model.SourceCandidate + for _, seed := range searchSeeds { + key := strings.ToLower(seed.AuthorityName) + "|" + strings.ToUpper(seed.CountryCode) + "|" + strings.ToLower(seed.Category) + if _, covered := ddgCoveredKeys[key]; !covered { + llmSeeds = append(llmSeeds, seed) + } + } + if len(llmSeeds) > 0 { + llmCandidates, err := llmSearchCandidates(ctx, cfg, searchClient, llmSeeds) + if err != nil { + failures = append(failures, fmt.Sprintf("llm-search: %v", err)) + } else if len(llmCandidates) > 0 { + fmt.Fprintf(stderr, "LLM search discovery (fallback): generated %d candidate URLs via %s\n", len(llmCandidates), cfg.VettingProvider) + candidates = append(candidates, llmCandidates...) + } + } } if len(failures) > 0 { return candidates, fmt.Errorf("%s", strings.Join(failures, " | ")) diff --git a/internal/collector/discover/probe.go b/internal/collector/discover/probe.go index 3ffd95b..02547ed 100644 --- a/internal/collector/discover/probe.go +++ b/internal/collector/discover/probe.go @@ -33,6 +33,31 @@ var feedPaths = []string{ "/resources/press-releases/feed", "/newsroom/feed", "/latest/feed", + // Government / DOJ / ministry patterns. + "/feeds/opa/justice-news.xml", + "/feeds/news.xml", + "/feeds/press-releases.xml", + "/feeds/alerts.xml", + "/blog/feed", + "/blog/rss", + "/updates/feed", + "/publications/feed", + "/advisories.xml", + "/warnings/feed", + "/alerts/feed", + "/releases/feed", + // Multi-language government sites. + "/de/feed", + "/fr/feed", + "/es/feed", + "/it/feed", + "/nl/feed", + "/sv/feed", + "/no/feed", + "/da/feed", + "/fi/feed", + "/pl/feed", + "/pt/feed", } // ProbedFeed is a single discovered feed from probing. diff --git a/internal/collector/discover/search_ddg.go b/internal/collector/discover/search_ddg.go new file mode 100644 index 0000000..199d2a9 --- /dev/null +++ b/internal/collector/discover/search_ddg.go @@ -0,0 +1,234 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package discover + +import ( + "context" + "fmt" + "net/url" + "regexp" + "strings" + "time" + + "github.com/scalytics/euosint/internal/collector/config" + "github.com/scalytics/euosint/internal/collector/fetch" + "github.com/scalytics/euosint/internal/collector/model" +) + +// ddgResultRe extracts href URLs from DDG result links. +// DDG wraps results in or +// +var ddgResultRe = regexp.MustCompile(`(?i)href="(https?://[^"]+)"`) + +// ddgRedirectRe extracts the real URL from DDG redirect wrappers. +var ddgRedirectRe = regexp.MustCompile(`[?&]uddg=([^&]+)`) + +// ddgSearchCandidates uses DuckDuckGo via a headless browser to find +// RSS/Atom feed URLs for gap-analysis targets. This is the zero-dependency +// fallback when no LLM API key is configured. +func ddgSearchCandidates(ctx context.Context, cfg config.Config, browser *fetch.BrowserClient, seeds []model.SourceCandidate) ([]model.SourceCandidate, error) { + if !cfg.DDGSearchEnabled || browser == nil { + return nil, nil + } + + targets := selectSearchTargets(cfg, seeds) + if len(targets) == 0 { + return nil, nil + } + + maxQueries := cfg.DDGSearchMaxQueries + if maxQueries <= 0 { + maxQueries = 10 + } + delay := time.Duration(cfg.DDGSearchDelayMS) * time.Millisecond + if delay < 5*time.Second { + delay = 5 * time.Second + } + + // Limit to maxQueries to stay polite. + if len(targets) > maxQueries { + targets = targets[:maxQueries] + } + + var out []model.SourceCandidate + var failures []string + seen := map[string]struct{}{} + + for i, target := range targets { + if ctx.Err() != nil { + break + } + // Polite delay between queries. + if i > 0 { + select { + case <-ctx.Done(): + break + case <-time.After(delay): + } + } + + query := buildDDGQuery(target) + found, err := ddgSearch(ctx, browser, query, target) + if err != nil { + failures = append(failures, fmt.Sprintf("%s: %v", query, err)) + continue + } + for _, c := range found { + key := normalizeURL(c.URL) + if _, ok := seen[key]; ok { + continue + } + seen[key] = struct{}{} + out = append(out, c) + } + } + + if len(failures) > 0 && len(out) == 0 { + return nil, fmt.Errorf("ddg search: %s", strings.Join(failures, " | ")) + } + return out, nil +} + +// buildDDGQuery creates a DDG search query for a discovery target. +func buildDDGQuery(target model.SourceCandidate) string { + parts := []string{} + + name := strings.TrimSpace(target.AuthorityName) + if name != "" { + parts = append(parts, name) + } + + country := strings.TrimSpace(target.Country) + if country != "" && !strings.Contains(strings.ToLower(name), strings.ToLower(country)) { + parts = append(parts, country) + } + + topic := searchTopicLabel(target.Category, target.AuthorityType) + if topic != "" { + parts = append(parts, topic) + } + + parts = append(parts, "RSS OR atom OR feed") + + return strings.Join(parts, " ") +} + +// ddgSearch performs a single DuckDuckGo search and extracts URLs. +func ddgSearch(ctx context.Context, browser *fetch.BrowserClient, query string, target model.SourceCandidate) ([]model.SourceCandidate, error) { + searchURL := "https://html.duckduckgo.com/html/?q=" + url.QueryEscape(query) + + body, err := browser.Text(ctx, searchURL, true, "") + if err != nil { + return nil, fmt.Errorf("ddg fetch: %w", err) + } + + content := string(body) + urls := extractDDGURLs(content) + if len(urls) == 0 { + return nil, nil + } + + var candidates []model.SourceCandidate + for _, raw := range urls { + if !looksLikeURL(raw) { + continue + } + // Skip DDG internal links. + if strings.Contains(raw, "duckduckgo.com") { + continue + } + // Only keep URLs that look like they could be feeds or official sites. + if !looksLikeFeedURL(raw) && !looksLikeOfficialSite(raw) { + continue + } + candidates = append(candidates, model.SourceCandidate{ + URL: raw, + AuthorityName: target.AuthorityName, + AuthorityType: target.AuthorityType, + Category: target.Category, + Country: target.Country, + CountryCode: target.CountryCode, + Region: target.Region, + BaseURL: extractBaseURL(raw), + Notes: "ddg-search: " + query, + }) + if len(candidates) >= 5 { + break + } + } + return candidates, nil +} + +// extractDDGURLs parses URLs from DDG HTML search results. +func extractDDGURLs(html string) []string { + var urls []string + seen := map[string]struct{}{} + + for _, match := range ddgResultRe.FindAllStringSubmatch(html, -1) { + if len(match) < 2 { + continue + } + rawURL := match[1] + + // DDG wraps results in redirect URLs — extract the real target. + if strings.Contains(rawURL, "duckduckgo.com/l/") { + if redir := ddgRedirectRe.FindStringSubmatch(rawURL); len(redir) >= 2 { + decoded, err := url.QueryUnescape(redir[1]) + if err == nil { + rawURL = decoded + } + } + } + + // Skip DDG assets and internal pages. + if strings.Contains(rawURL, "duckduckgo.com") { + continue + } + + norm := strings.ToLower(strings.TrimRight(rawURL, "/")) + if _, ok := seen[norm]; ok { + continue + } + seen[norm] = struct{}{} + urls = append(urls, rawURL) + } + return urls +} + +// looksLikeOfficialSite checks if a URL looks like an official government +// or organization site worth probing for feeds. +func looksLikeOfficialSite(raw string) bool { + lower := strings.ToLower(raw) + officialTLDs := []string{ + ".gov", ".gob", ".gouv", ".govt", + ".mil", ".edu", + ".int", ".org", + ".police", ".cert", + } + for _, tld := range officialTLDs { + if strings.Contains(lower, tld) { + return true + } + } + officialKeywords := []string{ + "ministry", "department", "agency", + "security", "intelligence", "police", + "cert", "csirt", "ncsc", + } + for _, kw := range officialKeywords { + if strings.Contains(lower, kw) { + return true + } + } + return false +} + +// extractBaseURL returns the scheme + host portion of a URL. +func extractBaseURL(raw string) string { + parsed, err := url.Parse(strings.TrimSpace(raw)) + if err != nil { + return "" + } + return parsed.Scheme + "://" + parsed.Host +} diff --git a/internal/collector/discover/search_ddg_test.go b/internal/collector/discover/search_ddg_test.go new file mode 100644 index 0000000..fab6848 --- /dev/null +++ b/internal/collector/discover/search_ddg_test.go @@ -0,0 +1,111 @@ +// Copyright 2026 ff, Scalytics, Inc. - https://www.scalytics.io +// SPDX-License-Identifier: Apache-2.0 + +package discover + +import ( + "testing" + + "github.com/scalytics/euosint/internal/collector/model" +) + +func TestExtractDDGURLs(t *testing.T) { + html := ` + + + + +` + urls := extractDDGURLs(html) + + // Should have 3 URLs (DDG internal filtered out). + expected := map[string]bool{ + "https://www.ncsc.gov.uk/rss/all": false, + "https://www.cert.se/feed/rss.xml": false, + "https://www.justice.gov/feeds/opa/justice-news.xml": false, + } + + for _, u := range urls { + if _, ok := expected[u]; ok { + expected[u] = true + } + } + + for u, found := range expected { + if !found { + t.Errorf("expected URL %q not found in results", u) + } + } +} + +func TestBuildDDGQuery(t *testing.T) { + target := model.SourceCandidate{ + AuthorityName: "Norway national CERT or CSIRT", + Country: "Norway", + Category: "cyber_advisory", + AuthorityType: "cert", + } + + query := buildDDGQuery(target) + + if query == "" { + t.Fatal("expected non-empty query") + } + // Should contain the authority name and RSS/atom/feed keywords. + if !containsAll(query, "Norway", "CERT", "RSS OR atom OR feed") { + t.Errorf("query missing expected parts: %s", query) + } + // Country should NOT be duplicated (already in authority name). + // Actually "Norway" appears in AuthorityName, so it should only appear once. +} + +func TestLooksLikeOfficialSite(t *testing.T) { + tests := []struct { + url string + want bool + }{ + {"https://www.ncsc.gov.uk/rss", true}, + {"https://cert.se/feed", true}, + {"https://www.police.uk/news", true}, + {"https://www.bbc.com/news", false}, + {"https://www.justice.gov/feeds", true}, + {"https://www.reddit.com/r/netsec", false}, + } + + for _, tt := range tests { + got := looksLikeOfficialSite(tt.url) + if got != tt.want { + t.Errorf("looksLikeOfficialSite(%q) = %v, want %v", tt.url, got, tt.want) + } + } +} + +func containsAll(s string, subs ...string) bool { + for _, sub := range subs { + if !contains(s, sub) { + return false + } + } + return true +} + +func contains(s, sub string) bool { + return len(s) >= len(sub) && (s == sub || len(s) > 0 && containsSubstring(s, sub)) +} + +func containsSubstring(s, sub string) bool { + for i := 0; i <= len(s)-len(sub); i++ { + if s[i:i+len(sub)] == sub { + return true + } + } + return false +} From e86fede0175c300efa25fc9d4a2e296d48c37c43 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Tue, 17 Mar 2026 08:50:31 +0100 Subject: [PATCH 44/58] =?UTF-8?q?fix:=20Wikidata=20SPARQL=20timeouts=20?= =?UTF-8?q?=E2=80=94=20single=20type=20ID=20queries,=20no=20labels?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause: SERVICE wikibase:label and P279* subclass traversal cause persistent timeouts on the public Wikidata SPARQL endpoint. Fix both police.go and humanitarian.go to query one type ID at a time with P31 only, LIMIT 50, deriving names from hostnames and a static country map. Added 8 explicit subclass type IDs to compensate for removed P279*. --- internal/collector/discover/discover_test.go | 4 +- internal/collector/discover/humanitarian.go | 60 +++++----- internal/collector/discover/police.go | 114 +++++++++++-------- 3 files changed, 99 insertions(+), 79 deletions(-) diff --git a/internal/collector/discover/discover_test.go b/internal/collector/discover/discover_test.go index 8806dcd..981ae24 100644 --- a/internal/collector/discover/discover_test.go +++ b/internal/collector/discover/discover_test.go @@ -67,12 +67,12 @@ func TestCommonPressReleasePathsNotEmpty(t *testing.T) { } func TestPoliceAgencyQueryNotEmpty(t *testing.T) { - query := buildPoliceAgencyQuery(policeAgencyTypeIDs[:2]) + query := buildPoliceAgencyQuery(policeAgencyTypeIDs[0]) if strings.TrimSpace(query) == "" { t.Fatal("SPARQL query should not be empty") } // Basic sanity — query must select the fields we parse. - for _, field := range []string{"agencyLabel", "website", "countryLabel", "countryCode"} { + for _, field := range []string{"website", "countryCode"} { if !strings.Contains(query, field) { t.Errorf("SPARQL query missing field %q", field) } diff --git a/internal/collector/discover/humanitarian.go b/internal/collector/discover/humanitarian.go index 32896df..5ca8e37 100644 --- a/internal/collector/discover/humanitarian.go +++ b/internal/collector/discover/humanitarian.go @@ -24,61 +24,61 @@ type HumanitarianOrg struct { } var humanitarianTypeIDs = []string{ - "Q895526", - "Q15220109", - "Q1460420", - "Q1066476", + "Q895526", // humanitarian aid org + "Q15220109", // disaster management authority + "Q1460420", // civil protection + "Q1066476", // emergency management + // Subclasses we'd miss without P279* traversal: + "Q3918693", // emergency service + "Q863734", // rescue service + "Q167546", // NGO (filtered later by hygiene) + "Q484652", // international organization } -func buildHumanitarianQuery(typeIDs []string) string { - values := make([]string, 0, len(typeIDs)) - for _, typeID := range typeIDs { - typeID = strings.TrimSpace(typeID) - if typeID == "" { - continue - } - values = append(values, "wd:"+typeID) - } +func buildHumanitarianQuery(typeID string) string { + // Query ONE type ID at a time with P31 (no P279* subclass traversal). + // No label service, no rdfs:label OPTIONAL — both cause Wikidata + // timeouts. We extract the hostname as a proxy for the org name. return fmt.Sprintf(` -SELECT ?org ?orgLabel ?website ?countryLabel ?countryCode WHERE { - VALUES ?type { %s } - ?org wdt:P31/wdt:P279* ?type ; +SELECT ?website ?countryCode WHERE { + ?org wdt:P31 wd:%s ; wdt:P856 ?website ; wdt:P17 ?country . ?country wdt:P297 ?countryCode . - SERVICE wikibase:label { bd:serviceParam wikibase:language "en" . } -} -`, strings.Join(values, " ")) +} LIMIT 50 +`, strings.TrimSpace(typeID)) } // FetchHumanitarianOrgs queries Wikidata for humanitarian, emergency management, -// and civil protection agencies worldwide. +// and civil protection agencies worldwide. Queries one type ID at a time +// with LIMIT 50 to stay within Wikidata's public SPARQL timeout limits. func FetchHumanitarianOrgs(ctx context.Context, cfg config.Config, client *fetch.Client) ([]HumanitarianOrg, error) { var failures []string seen := map[string]struct{}{} var orgs []HumanitarianOrg - for _, chunk := range chunkTypeIDs(humanitarianTypeIDs, 2) { - query := strings.TrimSpace(buildHumanitarianQuery(chunk)) + for _, typeID := range humanitarianTypeIDs { + if ctx.Err() != nil { + break + } + query := strings.TrimSpace(buildHumanitarianQuery(typeID)) reqURL := wikidataSPARQL + "?format=json&query=" + url.QueryEscape(query) body, err := fetchWikidataTextWithCache(ctx, cfg, client, reqURL, "application/sparql-results+json, application/json;q=0.9") if err != nil { - failures = append(failures, fmt.Sprintf("%s: %v", strings.Join(chunk, ","), err)) + failures = append(failures, fmt.Sprintf("%s: %v", typeID, err)) continue } var resp struct { Results struct { Bindings []struct { - OrgLabel struct{ Value string } `json:"orgLabel"` - Website struct{ Value string } `json:"website"` - CountryLabel struct{ Value string } `json:"countryLabel"` - CountryCode struct{ Value string } `json:"countryCode"` + Website struct{ Value string } `json:"website"` + CountryCode struct{ Value string } `json:"countryCode"` } `json:"bindings"` } `json:"results"` } if err := json.Unmarshal(body, &resp); err != nil { - failures = append(failures, fmt.Sprintf("%s: parse: %v", strings.Join(chunk, ","), err)) + failures = append(failures, fmt.Sprintf("%s: parse: %v", typeID, err)) continue } @@ -98,8 +98,8 @@ func FetchHumanitarianOrgs(ctx context.Context, cfg config.Config, client *fetch seen[host] = struct{}{} orgs = append(orgs, HumanitarianOrg{ - Name: b.OrgLabel.Value, - Country: b.CountryLabel.Value, + Name: hostToName(host), + Country: countryFromCode(b.CountryCode.Value), CountryCode: strings.ToUpper(strings.TrimSpace(b.CountryCode.Value)), Website: website, }) diff --git a/internal/collector/discover/police.go b/internal/collector/discover/police.go index ab813ae..1e61399 100644 --- a/internal/collector/discover/police.go +++ b/internal/collector/discover/police.go @@ -45,66 +45,67 @@ var commonPressReleasePaths = []string{ } var policeAgencyTypeIDs = []string{ - "Q732717", - "Q35535", - "Q15636005", - "Q584085", - "Q1752939", - "Q12039646", + "Q732717", // police + "Q35535", // gendarmerie + "Q15636005", // intelligence agency + "Q584085", // coast guard + "Q1752939", // customs + "Q12039646", // secret police + // Subclasses we'd miss without P279* traversal: + "Q17032608", // law enforcement agency + "Q56318653", // national police + "Q19832486", // federal police + "Q2102290", // border guard + "Q15925165", // national security agency + "Q68416", // national guard + "Q189290", // military police + "Q7188", // security service } -func buildPoliceAgencyQuery(typeIDs []string) string { - values := make([]string, 0, len(typeIDs)) - for _, typeID := range typeIDs { - typeID = strings.TrimSpace(typeID) - if typeID == "" { - continue - } - values = append(values, "wd:"+typeID) - } +func buildPoliceAgencyQuery(typeID string) string { + // Query ONE type ID at a time with P31 (no P279* subclass traversal). + // No label service, no rdfs:label OPTIONAL — both cause Wikidata + // timeouts. We extract the hostname as a proxy for the org name. return fmt.Sprintf(` -SELECT ?agency ?agencyLabel ?website ?countryLabel ?countryCode WHERE { - VALUES ?type { %s } - ?agency wdt:P31/wdt:P279* ?type ; +SELECT ?website ?countryCode WHERE { + ?agency wdt:P31 wd:%s ; wdt:P856 ?website ; wdt:P17 ?country . ?country wdt:P297 ?countryCode . - SERVICE wikibase:label { bd:serviceParam wikibase:language "en" . } -} -`, strings.Join(values, " ")) +} LIMIT 50 +`, strings.TrimSpace(typeID)) } // FetchPoliceAgencies queries Wikidata for law-enforcement agencies -// worldwide that have official websites. This replaces a static curated -// directory and scales to every country automatically. +// worldwide that have official websites. Queries one type ID at a time +// with LIMIT 50 to stay within Wikidata's public SPARQL timeout limits. func FetchPoliceAgencies(ctx context.Context, cfg config.Config, client *fetch.Client) ([]PoliceAgency, error) { - // Query Wikidata in smaller chunks so one slow response does not zero out - // the entire law-enforcement directory. seen := map[string]struct{}{} var agencies []PoliceAgency var failures []string - for _, chunk := range chunkTypeIDs(policeAgencyTypeIDs, 2) { - query := strings.TrimSpace(buildPoliceAgencyQuery(chunk)) + for _, typeID := range policeAgencyTypeIDs { + if ctx.Err() != nil { + break + } + query := strings.TrimSpace(buildPoliceAgencyQuery(typeID)) reqURL := wikidataSPARQL + "?format=json&query=" + url.QueryEscape(query) body, err := fetchWikidataTextWithCache(ctx, cfg, client, reqURL, "application/sparql-results+json, application/json;q=0.9") if err != nil { - failures = append(failures, fmt.Sprintf("%s: %v", strings.Join(chunk, ","), err)) + failures = append(failures, fmt.Sprintf("%s: %v", typeID, err)) continue } var resp struct { Results struct { Bindings []struct { - AgencyLabel struct{ Value string } `json:"agencyLabel"` - Website struct{ Value string } `json:"website"` - CountryLabel struct{ Value string } `json:"countryLabel"` - CountryCode struct{ Value string } `json:"countryCode"` + Website struct{ Value string } `json:"website"` + CountryCode struct{ Value string } `json:"countryCode"` } `json:"bindings"` } `json:"results"` } if err := json.Unmarshal(body, &resp); err != nil { - failures = append(failures, fmt.Sprintf("%s: parse: %v", strings.Join(chunk, ","), err)) + failures = append(failures, fmt.Sprintf("%s: parse: %v", typeID, err)) continue } @@ -124,8 +125,8 @@ func FetchPoliceAgencies(ctx context.Context, cfg config.Config, client *fetch.C seen[host] = struct{}{} agencies = append(agencies, PoliceAgency{ - Name: b.AgencyLabel.Value, - Country: b.CountryLabel.Value, + Name: hostToName(host), + Country: countryFromCode(b.CountryCode.Value), CountryCode: strings.ToUpper(strings.TrimSpace(b.CountryCode.Value)), Website: website, AuthorityType: "police", @@ -150,18 +151,37 @@ func FetchPoliceAgencies(ctx context.Context, cfg config.Config, client *fetch.C return nil, nil } -func chunkTypeIDs(values []string, size int) [][]string { - if size <= 0 { - size = len(values) +// hostToName derives a readable name from a hostname. +// e.g. "www.politi.dk" → "politi.dk" +func hostToName(host string) string { + host = strings.TrimPrefix(host, "www.") + return host +} + +// countryFromCode returns a country name for a code, or the code itself. +func countryFromCode(code string) string { + code = strings.ToUpper(strings.TrimSpace(code)) + countries := map[string]string{ + "NO": "Norway", "SE": "Sweden", "FI": "Finland", "DK": "Denmark", "IS": "Iceland", + "GB": "United Kingdom", "FR": "France", "DE": "Germany", "NL": "Netherlands", + "BE": "Belgium", "LU": "Luxembourg", "IE": "Ireland", "CH": "Switzerland", + "AT": "Austria", "ES": "Spain", "PT": "Portugal", "IT": "Italy", "GR": "Greece", + "MT": "Malta", "CY": "Cyprus", "PL": "Poland", "CZ": "Czech Republic", + "SK": "Slovakia", "HU": "Hungary", "RO": "Romania", "BG": "Bulgaria", + "HR": "Croatia", "SI": "Slovenia", "RS": "Serbia", "BA": "Bosnia", + "ME": "Montenegro", "MK": "North Macedonia", "AL": "Albania", "XK": "Kosovo", + "EE": "Estonia", "LV": "Latvia", "LT": "Lithuania", "UA": "Ukraine", + "GE": "Georgia", "TR": "Turkey", "US": "United States", "CA": "Canada", + "AU": "Australia", "NZ": "New Zealand", "JP": "Japan", "KR": "South Korea", + "CN": "China", "IN": "India", "BR": "Brazil", "MX": "Mexico", + "IL": "Israel", "SA": "Saudi Arabia", "AE": "United Arab Emirates", + "RU": "Russia", "BY": "Belarus", "MD": "Moldova", + "ZA": "South Africa", "NG": "Nigeria", "KE": "Kenya", "EG": "Egypt", + "ID": "Indonesia", "MY": "Malaysia", "SG": "Singapore", "TH": "Thailand", + "PH": "Philippines", "PK": "Pakistan", "AR": "Argentina", "CO": "Colombia", } - var chunks [][]string - for start := 0; start < len(values); start += size { - end := start + size - if end > len(values) { - end = len(values) - } - chunk := append([]string(nil), values[start:end]...) - chunks = append(chunks, chunk) + if name, ok := countries[code]; ok { + return name } - return chunks + return code } From 10dc4ed031805368ff2471aa3d6f1ed1f86b14e3 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Tue, 17 Mar 2026 08:55:10 +0100 Subject: [PATCH 45/58] feat: add Scalytics product and contact links to footer Links to streamingintelligence product page and contact page with UTM tracking parameters. Referrer enabled for analytics attribution. --- src/App.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/App.tsx b/src/App.tsx index f665482..b3047af 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -295,13 +295,18 @@ export default function App() {
- Scalytics OSINT // Open Source Intelligence Console + + Scalytics OSINT + {" // Open Source Intelligence Console"} + {selectedSourceIds.length > 0 ? `Scoped to ${selectedSourceIds.length} feeds` : categoryFilter !== "all" ? `Scoped to ${categoryFilter}` : "All live feeds"} + {" // "} + Build your intelligence pipeline — Contact us
From f487cc6a7369d59c10942df19dc0899f59ac2364 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Tue, 17 Mar 2026 08:57:50 +0100 Subject: [PATCH 46/58] chore: add pre-seeded sources.db for fresh installs 3.2MB SQLite snapshot with curated feeds so new deployments start with full coverage immediately. Entrypoint copies it to /data/sources.db on first run; subsequent starts merge the JSON registry on top. --- registry/sources.seed.db | Bin 0 -> 3350528 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 registry/sources.seed.db diff --git a/registry/sources.seed.db b/registry/sources.seed.db new file mode 100644 index 0000000000000000000000000000000000000000..88cb259504e5c790b699282c29884d666e134620 GIT binary patch literal 3350528 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
    %^j|D+f40C~Xk_WjRxEwK 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

    uK21y#aaG67pwC7qSEjQBHhII9DWp1Pti&QIiF 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

    2Vh!kvZxW_{dU%wuB}Z?Tbf$8 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 z z>Zob&s+p+S2)n-R+5-zpGAOOKnQD>1PLv;5P{M#m03`JS@D^mJwuTi*ln8>sxF>65 z-mrcz)Yec~LcOpeb}=`t`6Y!R_C&{3_k1zUjwnPK+FQRD)S0p?tOlA&HYiC$h9#3K z*~9rof{huCpHhmJqV*z>KY(*Xno5k{!e}Oy!tg!_W4M!gg(OmBTHD$DqDZOpx}gXF zCj(s+`%DBfeMt}Nc~P~RW+0VBQoiduzWeOCf9c!x=l|o)-_C!qMySf!c?rJwAXvfoYFdO@#fvDg*EN40N)`gegW0p>}Z- zTUQ+`uNebx8jBtHbmeoT=EgCSO7^Yx^q`CN@V*zH`KwpT&I!$%qu6P05 zwP`RfN_}^qI=5Nf-K4rUwcD?^S#u?Q*3Pu8=Pzt+zr89rqbm{^~fctda%{#aUlnEclI5u`BnDAavQ5Li&a^I=cTXL4)AXoN@{Hb(Wewq!YKsa)d3 zB&|o4e;v)7{cY_Em`rve50xyQAaiZRWy0u5cJd3m!-^-wa$*HpAhz{uLGUga|0+e0 z^3W^9_vEndW$bY^KkfV((omSQ*p=0qN!@Pc1qE@6z1e2HoVwkE03A~dNWO4pRa_gh zoFwuS%54;RYOz?ioWwmNBifD&(4&BYh1IZ{VYdp>3!X zq;F}X#zC~rmP$9?qKmp8kmD#}TeK^)_gENv84Nl4SQ>uTM(_2|Pc?BChI)3`*bm4z z97N#dK)sig{?&r|&8;a^O31(6W=X9L5^LE7Y9A1mK@VkJ$e=n|cLX~RG^J}^RtFZ# zHvFq{u-Glbr~|O9JccBQJxKqvO}hoZhyDS3kA)4>1IjZ0)^5q)CPq7b(<0kx1c4-w zw;s5Iz!7IjuRT$Hk*Ig9mNEpwVwpvTDu+M-N3=p}`t@dLo!$i)v+~*C*t)0z{(I zQkg}{c9sbTWWa9iq#v6jOAN1gN0nVfTAtUwp@{Lejov2Kxb)@Q;L1`*1{88;Z4vic zIYBo!C#{JH($}M%tZLRih#Fc(JPO^4&03ak6St@;4p#6c>d1jWv55HdYwtJ2j|^wP z#>7G?ORd%%zfr2hYALKeZT!M6UCCsXKxH66Ns5`ZmyjX;x4c7P7uBy z#SrR3o$O=vavH-}PeCgRad1#)1NzC@XtlnG z0m^2Fdw^N8YOhDEYJKgaHb?1|pVKTCxB)LLml6`4W*c?sG0SO7C5D1Qb{xnJi^A5T zU<6>$;k{82f19lcxp@XT!OLA@6(4xsA>h*x7 zQpOBmJwQJ;41_brny^|^$=eTA!Eq!sA|5tht4~bhA&N5URK`^7##@#s+8_OsUaon{ZjmLLm$l-t zEHrDQmzoEys17@P?MXb9<&tFMQfa$P_06A zXa4Ye*~T2$9D#G8sMxI4QZ@x%|$3{<-+Z4kg#PUFs966u4ZGo-40c*eA@!j&C082WY!J$C=Wpl z%CfK3FV;Fa>|5pyiK8EssYB74Uir|nrK&i(eSp8s#|SVsVpuO za#>2{3(A{(D5JiaDziZxb%QxaUMt}%J|trNVe_NamQE(uCabZj;(DH?Nd;t5wMD^W zf-UoHG`6yCusPZ+OPD=~A62OhyG^T&91{hkjX}MTOtMx&!?5iMR%9UWgsl55l^3wO2k9V^2`Ohj8fBf1~VfDv6g0gwUr$h{jv6?pF2{q?`2yZ_PGQ53}saV zV)nJC*lKP<*kPWtOcbdzt;v=0+Dm^?`b2-`2IGqqA$r!@jAG?&H|r?&#W<>Dtv5@b1{weW+_+ zM`!o0o!y-~cXsv+clYe>33MIod~x?P`}TI6*xB9H-SyCNa!2$~cUM>U!`s@o^>lac z@7M|Mzm9hAuI_I6(4HMTckS5O-M#O?{>~l{i+AtZwyURe??df92X`LXvyb8b+q#?D zKh<`*`7|yL)o1~(xmQa)%n(0VX;Y4Pw=zrqD+ z)d6nvAFROs|9bxV^Q*HwV7{_jaRLCyx5UGqGav%%0scKfH-Q0%y>8bX5rKjKukZ+L z7XCl17;s3gLl=I4|IaY>?!w%UESTWzK^7Amqhi;L&o>Ax{FwP(9}y9z&e>aL&nWF7b(pY4~DM zIatDhQISZmh^T{SnXSbxDl+!&b3oMC2&jiiXdH5=JW@HzrAE@E#@|?K{9#v3uh|%> zITIO;jf_Nu(b$>c$VhZ}`phN?3kqN^EdA&EPXFe&9{R4yFZI3er*ED=WV^O0!qN{n zuL48zsj;T)Kac+MKvv$HvVz7TSvguc!evF)WX0Q9R>J=9CdtZVY!n1W)6p}+5M~#E zBVE`eX+aUprDgQlzTofn4*&TN9k_Y^OP?S70~7ekGI4LojNDW%Stx!UFBg zdsA4@I3z6RD^Dn#na=Zv_rg)XZRKRg>b^|UE0WW2LIws|Fp!cxA+Y_juzQJ&7J7(5hbJR`d1#(LxN-5_#jw&(R*JvpyWf{f;Sh~3DEvgXjf^eMN0IE^R zmx)>{DZ>^LND#n;qOO}Gf?;-(1Z;hcnJ2gZ-`VuhrX4%B3){Tyk*$+kq_%wPQp-y7 zCmcUz|7F`>TYtv#*`|-$o4)L8YTEw2+gyzM6-Ww%-@e*uaWr$(fj4$S&rvLWNWj5t zIU!v?Xt6milNxAs4m!r-tmP?a-i|A}@5%=dwucUKOO{>GZSJ-Nq2Ae!15upc?OFD2 zYYJDMsN};vUCw6oDOpbh^SY$8)Khtt*37&hGL0t={^K3qWikkpW z8$=gZaMg~@lS47w(NhrHs9Yf8y(|P3)dV2_f-EtoZW7qzPAA(=AvI!ShEj>NM-BwNylzk{*y$C8NwA)zq(6H7<3&M@ zb0WWp(#LY>ia1n;(*s=n;o^Q-&gK`$_-~!+Sb&LYk+_(lPzBHkH4kcp5)%t7v7(sc zxkuF?B{=BoQ-XW9meRe|124+tx#hsJo2ntQ+!o$%>>@r_NbYMH8q=c|MaY zu2VrAfQ9M>&c7^m@k$;ZZ%ORU|BqEp@d!!B&)|E=oLgG0jpJ7u3|v zD^1<2W24=;168J$UF}UL&R2raYxp5sG+mHN18zE`&miauk2mPocI%T68x=eA{Pbij zCQM9@pBbNs#fQ%u_;=Kp8mb`>ld5lUqVg9-T>vQ{)TA4b^h8XuR8&}@rz4fwWoLU+ z--tr~{KwC`CYoJTN{v9*@S(jBk=k ziE?3H$oLua+!f>5{AFn_BgM~DXyk*H;Z~>Ow`DM}>l(fr~z=0wPmmDCBhf z49KGli!-JBH|(@VJsIz}#xPZPhHRLZwEw($_KL~|zW;pX<>h1Bnod?6yhR)IUVq3R zHjjy++CmjQFgY%qj-2JRm19$rgOicCFcvu*nVcM)8r+m}Q>M&|9R=;Sg1>8!v|^Nw zp`#;}!tzs8Xv>|uu_qibk4J;@os0-HB8LAP?-*1Fh%p_Bi(&BbpTm1FY+*W z#!ZW?>NSVQD!Jt++nb^6ffRcih}`Pb6`Z zqN|$&Hg8Z9yD2;7MeZMOP~?87oMCF#KVF$zK7!$Sp7-m=%$hg=V75C9&!dsykwMI} zgV7kqEMatD1iJtDCJ8VyVqVe<)fv~&AVuy_A7K`>7b57g`Hb|49#2S;%nNxI0Fj?yk7HK zgZPdOVVLTtC5I55jNwcRysH9cCG_b{Xj~;X=8Zf0ta&brTs=7YEJmwG)!y7;-kW&> zjfZDe+<`&i^k5vqtEyFnp~z&^NH?oW%6-pBRQ(Nvc-;cC^MA|3P3?cu`VmJN7yrHH z{NMcc`txsiKwbqvfaR@~R~3A|j*iuEIhO~(j_AUHV$v7#B?5jWs1^(W!1(R}0PE_V zwmBl-R2~$2VCRALmq7ce<3cDX0Fo~YwS&M|s-QaIlvBrq5ji2{^6-HhPbSL?8SGgm zpjU(b1p0@ZFeMjoHVt2kW7y=*=aZxlNkVJD&(uguKz^cZb$v`wwiMJeZ%kJn;r>tF zN*nWkYFlYrw%q7ouK7%HR}=x$7m(zTFPu)eb>a7@fy@xW3midX1F<-e2w?W67Y&M+ zDG{k6fYgaCI`-XQ71ELV;8qer-{T6pML?{Q!CD=>*Qu!Wr+3WUjCZ{8)h~YSf>F7s z%e$F^F^b_?h%n~`Jg$1DZmbFsI+6x}UZk2)t6^g_h?>k#C0AHry-Lv7r)pf70zwHU zeZ=uc%1fx?CCFS+K=}y~5d9NC*K!dt^7!r!Q|KPNqj)Y+qy>0YLn$d_FgzqnPQvje z(mQ8y3Fd+GV0Xl+dX|g~NZ}d+q!)$>a8V{f3x?dm=3H2qg=P#IeWm0+C~bkjE8u9p z1U%3ZU8y=o=;*RbW*^Vq;m)gg%#{m5b=Pf-26g}f90 zVXOtqaxnu8M<}}ZEdU;IIwKVl7;g!yJcq~7eWkM!A$XRc2PC^-Aftg2tPI_#ghoT4 zm@4GKCIXTX8PE*?P6g0tQt@u(cxNOHljD7-9ugCwufDJE_|uQR9gue$$Fpjkp%LrO zOC~ArG&fABmLk<5O?igTYR(EL4J4n9Njug%2&t_HY6!y7ie)x8Y*{U;g}sn{oH<-}(H7PZ+!B zgXuOeJeY1DOtlU*s*++(5BgvI+*l$L1+eyDW6Xbytk<~ zo_R$e@M-YurlExrqT^>{1EM?3&fWMqp#XhYVg5LA@zQ<+;QQGWEDK8XI#xz-n!vt= zmW%W>C%;k>)Ds^AZVmFsc8vUxiBSGsSbTaEN}bFr3#-Av;mvY4bc_hUR$y2q{h~@s#qQojPIZN#}hR0a%*ADdwE+xT$Z*{+mhP@|XK| z|L0$~wfx-)<4C90r`a@oZg`wni78@%oY*}9VHiibSYVA|r&FDQv7Y`q!r&-1zNypn zdK-Xyw_8wFOdL730UiiH|93QfwW8rM7>rIctQ)lKhbcSYLuvN_Z30eji)4HOF`_eM1$Gz* z&GKa_Ns4ifIV{A>a0Y{ZV=<>LtZDI~U@kecJZiBTHLMGis7XQ*wTdaM#>>%!K@5a= zakPwh%e2bH5Q~*=9dOnDzx@Zx(l@=;cXIJX;nXk7OwVtcp9RRnI#i&+(A z)uKBdN7y}Bsoopr=L6)bIqH|%4&7+E4QMv`I-%P_md|T&l3^2c+f)cA^I^9?;7$8# zU|{PdB|sRA9&@C&_2DF=vr4EloRb`dIkRd41qKeKhm zkv{Kpp_gC!&TP}q8vA=q>CC$Q(E1>^REYY%KJ@_K7L{V+!q9MzGEr8&GkjYBr;gqg za4OqPdVK-E+gFR@+@Pm>jliiYmeu+_eG2Ql28w8=guX8+2;ET%Zti$;x^i$Rps-#9Yi1{K6Z!t3FFW&ywVj@`fSp-(JL{+91A`uyke zzjg5M{&bVNe}jUVObn+GwrP6-Z6S$7HcihS_y&~-j{o;WQxpEX!{3|FFc3g1+yEYL zYTj|tVf_zH>j4|w8TPx zBgp@4ZdU$n1?~i)pfPAB>%7F^QL3O80CkxutPKGxXIX~})(ki^AbVIcx1Y9DhBfF6 zyUhkV!?o9R*|0fs#No%@BLoe*ouS6iXUG7d#sKUD=d1wPP|!XQ#_&IE`F!ej8=_J& zZUd+eq2u8eXedCqb)pd5S7Ra{;d@05qq5gT}@hGh2%jhCNuA(TK zx6@Obr`6&&%rP+m84l(H9wSlo-vkt z_LMT_z^DU}QLp$b)o%d@sV@LM;6-^%yF%mCrAvS}tio8~bw4a|yPXU-81SD?FznX( z^4eLn0euT7rQ3)2HDt7~b{W^Y=0-<#D{tBy@HYZ-6>mMN48UfArA7Hf?OQgRikrm; z1;FvlGBrE{4AMk43oDVL3c?61pccR;tp!+8z)Rx!rduW79P2U%SUi39tSt)2gA&e$ zCG;{oz#(~D=y50%p>)*(9+l>^Yf~&e41l)MLebDUly?6*|5J}Jv{@PILi2qP{eeb> z2R{$$;Oo&3tXp+Q48Ux~#NDQh7h5n@V;08PYRe>NR1`jd=`AGJ;?+?Cs}^8H7m`?% z9b}SHDJbIyt!EDE#z5Ul%C25>%(D~&Rjm$z1eivXzAnT%n??56f(^?)5H+*)7CH?e z8*@MmUhaCBW5OxuY8YQ&$HX4c9B6OmENn_b+Q11=J3fWtYc?~{bVpMu24?o7VD3Fk zDUqBuS7#Uny3fv58}>Gs%L9!UD=dIFn*A+fx~apLM3ib6#~^H>dt9>hkI5qy-5QTt zS{=ZE1dTjfm?3YDW*dyx)MXmQ(Av!P0=hz)Wvv=!#rzG_v`OQt9;IJzGk}8J!z+BL z37|Ft2z6MoR#3JHEmpatf}hgDso4f&E4E}^?yPnthuVDrnTjX?R(a9TA??;?a-jxr zC-ow}1_Bx&2UP_)B_ZII*eaXa80)L-l5&R!EtjNu3C53Wr|>N@s;u7t^O$Bq)oh@T z%qwpxh?mXQmNE<{;k(R`FsV&iZG;0{L|lqoS*&w1@FE?Sm1vL}1|qDD?8S zYCAPoFKw;ZwZMwJx`3i&fKphTg}eFMQPkjar`js~U%RaZmW!oKxyV*)Y9UbXE!bER z*^j!np|zOJPM{>%C+a&&rS0LKot;P8yZ3c=?(E#%v7__JC-HCB?w%dH1BbeIb)D|) zKDP6Sv%6B z!%1PqQHe5JRqIL%Y*k@G0-$baZ6GM3=4bg5JIlYe z`}#Pi&xuy1#U22ASXYKRu0FF`xW0uSPUbZw9S-iFs8Pg;DZfVw2Bn1CmGIO&Go&kW zUjrfsG#*a+kJB-J9oOCU-jy>w{(UI&vSWFOA&yv9_I2E_u4LfzfZ%f#r-Fpow(PxT zQ%H)zPn=37L!qE25#~WPxd=?T+~o1#t|dX?9uIN(l``~z63|4zNeB~a?0Esu4&zzy za~%WVNODdB@8Gp(uBCbID%%!0E6delCA=c$lEtK$%c3n(zEn!`C4rQvgwk&> z^k>d7G!~6VxjB)`74{3yxqDr%7lh|Vox?8(XBM#sNJvs)R?egZSUt?wkKSBX4O%*hQ(I#)^(K^KBYme^zS;gGFU|FJ{np6U^fS2y zjN?0Z?|IR-+1R$Xv4=u^X*WjSXyT_( zEnU5EBbv$KE*G4(-k^#+6MDKWnh+zm%1vyVw+3 z*;|p7IkaOry5h(sC9ymw20Q_`BqtK?R64|i>ZdOMaTg5oYUfaHkarrMJ7}?|H*!(MH zVedLG14}5ETq0Mz-truW1-gV3nZ+zmQPfft$?z2^0_$Z#WXXYxj3vijSJP4sJ*$o_ zL;ZcR4?B+fe)K24{D%j=^`+N~&(_H!Rh9Xy7ZIk<7$!Z%Kkp1*^;aLM^WIQD!tP?; zThFJZaWx_S4LEf(odwOE^%`fzxi~A82p>0sdWq)U8njs0}*LWy{~5jm`7dF146#v_MWEk!OODi(QC%G1MY)XqAYotWy2 zu6*a0|7P%&n}BA>nWW7zNur&;E1eG<9DdsT0=iF~0{ zo`FxH7O0Bu#1z6dKy=M&2QhDs&`z92)b*=Yvpm2d6W*A~QoiWKH>&ix-T%g9&Pd)D z0Vdg0W*+XPd5xv7DtE?rv*4YVbZ;4-Mrp#r497N=RFwq@lR0*l)rcX%Z2#Z%MpOHv ztpoNKaPh2R|9}1AYmak+_qobbI{EJ6@*Ph4!znn<$R2OVDBsuot4n-ue{M$kZU5EPG&kHupKY%>L|-pQfKoCN8&;8YMMFj^2&deJG(!{uJgF6DCKVg|dc1~_K% zzUa@o`ocf*|K5zB-}0w{i30)SNI{6E{8M!Ly5WLwKF`5-mN{it2Z@dK!e_!LBl!kE zo=SD#g^e5|HVC|*YUl{O@?9>`ubTgJFZuwqG#qu5uYLshbS1O-BB4J*EizNa^0wA>U7hjIW}=Y^aH$u`Enb-5 zeIE6yNCB?S!k0TUkBd`;{Dg?GJV>s-#07o464nI$(CUe5Cl}?g&*yb{<)k~2tOnPt z`u$VnSpbnXS6H1MA08710NqETOkVBL@#(QCNb?!EwFBJxynZpD^j@PdmvaQ2S^{hU zPzqIvzLcNMVW}vKqR1WAnZPZHb9l3yoLg!v;qU*O<_~}2=WoW(ygB`e6Ri&he^=ABq&*2#A#sleo zAl)YJO0GcNyj+8|0}0}=I`7{6eJ|3jo5r7AeUZy|l;H-qw9tC}(5k;G$YK~1co-*~ z$+Y(_mO;?(>|K_$A+F#lF?OT4V z?eE&Wt>;^QsQEuNA9OhFbGBc!wOS8a=9{j3>~;Kg!398QvTy(G8@;f9*veRg+ZeSv z8KG>2xeE-3V4Xt$Cxh8G7(|f~Oe=mZ0Q;xEPB2B=D+}%_(xNF6E|3;|p0LXtvhg@j zesQ`8>5*(2|rNWy@1Tk#<*DxK4nt`zw|tj_r@`?I;)X z^MJh)6TXlu<#Gqoo`ipDl7aYv&qO#fDo4kmpXkqIGhcZ#GmqWPU=Ge%r6pnL)-M1A zFq@g9hbbU$&1a74S3DFmQ{k2h&V=%Y6Dg636;an80!~dL;ppJxl;9MmO5{DN>c^=4;bGdvre<_2uSp?>tT%7Ao&);A3g#7o= zJWm24{X~R8WgULPfJ+&0`CJ}JPNmZRa9n|x90uT8{uN>HtN=fCVskf~bZH=m3=-!q zP$o?>It?^=4JZ<;4I;~lmtccloQ_u_$B0*p7*`zYuM;Vm+Ae@L0``pUjz8RnmYJgfs|?Fj@LLeig~9vOT#CXB=` z^fSQnap)^Bk_}BqqQizwiwd4{|LCxk9do$=z_dAj_aJaeKuSCqtpos94!Q`FHVeoy zfFTlTzsK*2fwvLbAAp`j$|XSS(LPa#&7l41BA!o|0FZcp4P`QD-LauYfI9B4JY6Ht zY4~%x+zEfegL5Wzs0|5627ol(ABhhN=cOxeeJ=af=V-JYkV+D8W#@#*98hL}qf%T# zX|y-q`rQ2qdN5Sq_Zp7FPGE|kIAhihZg(1^Qz{({C*={$4h4|zK*k5+UYE-?5oaQU zJ3sF9Q^Y+sBj7W`!Vj+6#ox33|N@`czCkfVij_|a#3!^DEpHkXQM zBN%@$7v!YqSmk|y|2`p`wS_Mk2zgT8gx4i|qwph~q28aF%a(;vtiCeCScCEQAWJlM z7nfmz{mzGBY8X@W!8;7YApm;&D_u2`5e$Z;geRN~g(Ynf0>tGbQ@6gS|E-^xiktzG z=ueCc4UP)ur%2H{0zFYd0%^|N{YgP6Sl_Q2N$~l~yJ+-f+3S=sJ!|9aQBVkeEPDP@?be#s0IzhU!Vf^gi7=i$; zPUHdOBQe|z#)Qf7(Ob)78hHSn?c5c1E2-wNb0$bvCUXQjoymyM>?;tpaz(mgIGcfF`)Lw zAcutI8=oS0U#zkTtQQ*cLE#jbU#8w#W?$1Apn@5LPE>j0t>uxomZ!$6I?{XY6AEH4 zgaf@I0}C4JC4f%`&@bF~fn6*ul)xnh;xFPzEXjoWi=%4vAM_rWQowUrCX*=4ue^T| zFo>`@4A;dKPFI}pIF{qU*}=TlSqWU>2M;U)w!v(9Agy==|U}{ zZh6I_CePCCTgxO-Q(EnkeoBZ$2ji$yO;L5vb!sA5RBaGJsyJRTFbPMM!F9N#RNEDB z1BzHE7g1djlf!^FpwTOe`U*_=7({y@0z#bXWX=_x$Eb*N(s|PFbl~+^wOQJ8~Pp86Opo@lN+#9RN9hh=^2sq7U1Q1bu6HejW1vAx1Z=@F# z1!da($FX?Gq|*#qbO2}}6ok4V-?0>(tBvMypgT1SV@JPmo?()rLQipE0|Dd$Fjrva zj)SkD+khis=9q8_4lQzaNr)6sc@!i}W-b$_BFGV9N|-gBbX-K{5JZ7TnHGyY(?!TXOWLNYnu%&69O@a$YHbnqD z@GL4_nxk2g8TvE~DOPU$qx6|=H{;`bp8UA$7dws3gqnuBtImRgvAm+zq-zH%S+3Qt zbW|j755u$E2KSR<28k=Uu!%$}l#o41cQRNFu4_P#N9oUIMr;ZzC7@r6LK-lhMd4C; zo;WQCI9_nOV9Qnzh-i}fI(Ixk%YkQ*_PVe`Gj7sZE*L*02U_O~6orhD2xbFLg_V*L z1lBqd6e&Rzh#}RxU0|ie0K(QdGR#wXO2CdpN-z^j6DIq`d2AwR2+o1mHl4@vqHpy7 zT{iTyk^G_cTqrgj8408g`q520D|TZ4dM8lGsud_}uSa0M@k(WG7xROv9IeoH zfpC+%Dlf0@OVE5@Tok=YaGwOy3E34)Dq;6192nJc5+l(N7tg@kj{J&BMQpSdWl&KZ z=}(`frMl1`j~&IPV`4T#&t`;MzW`$^#=H#bPPvc*Q3Zx3{m6vu^d|6WZ%TH?q3x1W z1Nmgp86{$rVl^cqZYU#)oO581ix0_=%X1MaUqq@G>vPpR3mk&_P0PSwU+jrvpT6=+ zw(p^z|Nc)u{+-`tlo6$V%mf7K2rOfwE;TJ@RSAI&#SnuIS*nJqQZsOuQq$Ohi7aJx zwYD*0Vq&+A(jso7*+)&<)EKcTeQjLM7t&HT>&(#7N9!j_=*3(8VF4*L9IIh69cWz3TL-T1wY0x%~R zo_Rb1?DWgut%gFBe~yfO@V*fTIqRjd$Ph(hu9eYv%JO|LN+VJoefD z>M=^Fp#00<+`Q##HIGXvWuql}vY((2SQDu_nz^K|M&go{Nx}`2v1b zkEno_-&=n**P0&}h9aQ3qhl^mbTaimqvaINM&i#*Zz4TspaHwz@K|5(iO2r(HzvRR z=Jbz9KkxYGzcBXqnmRx;)b)7tlIr|t(dAWkQ+!{uk{cdFnAYiISnwBA=Nv;~rKJS` zPCjx+yJMi8v-KXGhcL=&x6(@6EFe z`p<@Qe^*n}jth1ifctOn1ZIH_$->smJ?8+Val}%YQ*j!O02P6NqJX3TUj^)1^FVzf zgrwyicmfCnhfVnxSQPAjYYT7Y{MvK$8exPHECt}z9L)3>aBl}Jl`;Y89Y87oWUx6} zTUBQ|hT}n>Sb^6<8yEnWFsupKBmgzSS}XyzK?TDD6brWiVqu68h!qRE`~ijv$x=$l z08r4Z#k2z6z@Atw9Ffa_ECB$HR}?&lDgwol1~Q?9H3MWqy;N|sPS@5a7lt(_!dV@( z<`~=^kU>1mqQYufR=@}yTTpil07LoLs{CtH(OZTsgj`3^G*-)Ac14wKu~Y)eo31L1 z3|#^JqnVIZnyq_{4^R=x19sK6HCgqF1fmGbs@-lc13{62-l-X~0uF^9qs0iQ1Xy`R ziD8hb0d|0v<&0HewaZ1RxR&IfQA68pZJG!F?H&aw4#0yzC_!y5Dwt>lC01Pf0PALi z703SwG0ymBWz~pEpx(-(S1+hDqT9AQI2H)2e-#!4-BA~cFYqEd3F|)U_jdIHdE`;E z=M8^Q)mDOBK`9I$IP3+mK&*|zT;@0f)oHP{C@(mUt8ZEXoHmJ~Eq7Ks6(R1y5CTx(C8Z7oR&$5drW2`A&77OGAMc2z(}Q6r{OP&I31ry4J^CM4ms z+U9_dL&z(-F~MrdDy^h|AfcfEjEVdl*XIFnHHFfw4#}+Ym1U>98h_(uO8Dq4Swn3P)pEIF(_^iz$Qg)xvJ_JfuNU?2V1 zZHv;9QWB~i!f3QPNEudC@P^Qd2t$cF6a9UW+k=$pvpROG`cp%?zr) z7iFh0P{|-5CZ*c|{!yTS>{bUYq+}IHlDe$bnz_WVgU~%FN{6)#`XzQCUu2M1JU8gY z{1%-K-J-A-L#${?be9=`UZFf_>2?@xaZD~MLH!>9L!ZJo&8QTPgGd0UEe-$(wE#H^ zR|n|_^{fA3Xo@vqcfLipK@YPQ7Z`>mIv8??YQ-SmqHq!2MlI3U!bW+E6(~i|AwcWp z4x57!Lf+oZ?9>QI%VA?b)b=);JqMk-@(IPk1fZFT#nReI787ehw6N8h%B=PA)L4tz z9ZBM|XJM32K$*>BxUUfe890vm=`9TE+rQ*=LPY z*wai*t+@px+hSQpa{|3cFV}YLwhJmi6+ny#Qbmc0#t3|mF&Ln4vQDUZ?;+7;?Z^Jr z_b3Xl{!wqEK1hH2*)N$7K7k>CK_05OW+sypaBO*75x^PsJ;(=#oG_zZDr)OTXBCFg<0-E2(`Ml zLUI7XN}68_p~Cj!3H=>lzv>U~vFaT`rd9t4Hn`c2fuz|^>m*t$HWL7>@^e7Ds)p5E zQNLrIPxo2PE9@3BsE@hkl~(J#%<$*b^4hQ~zr7C?pf+KP9R}}N7Q_Zl)FvUyRYypx zgKe%16+w`O#=mtd!%CIG7mciEQ%1Q+5C9?r$7Lnei;4D1_2s)2N2->_QMF*Dq1$bs z-J5B*LH|-S(!W-8RX)Hg%Own5F9VBPS#@L90mdx9!FbtLmZ4^5qaB4I4kk+WLJ|PU z1i7p0omQ)y!a9I80aC)+wK-j$k%4WEAypmq9ky0g+k?5S1(i)h-ZB$uf{Wy3W3|C5 z$JU%Bsytn1W(y0o*_$(RdQnc?wi&Ww15`LWR=vF+;mW&MCP-@~-19jL%kvAk!JxpW zKP>d}Yx68bsTl0Pa3F<`cqo%14D*&P>_iSA>~fZ^WR$UuW-b~B?nAI>hHkczV4(!~ zp&H;nBv`uJ>VxVP)fqN{>%K=lsBu)b?Q?V>Q9}K}*Iv%u-lf)9bM`VBNUG@TO0C(f zxgt;^AG1_)x~}jT?`+t9F63DZs#MZGC5ZX0a=F`L?>YG7-hEv?J3IF8+|_w-SBFp9 z)!EU})wQp^5_{}md*`0R?LE6XD}nC)-MjYg?CRLv-d@=QG{6HryE}FQ+;4B!j?RbL z_wU=WYx$Mudb&D0dUm#Vb?kkpa%yMij?T)|;m+;bcJJ!waUR&yy{)Tr*Ta?my}J)| z(D}ckDcjWk2W_{S-?V)gmoh8jsQ7pKkxxxTaGYI zu@zu>tB2=H;(QvM^nsu|;Y#@3K|k>S`t#HdCiiE zj^@;q8XBYPB*AGe8sO&(gv~`GHrD4GzwyPz)nZ@#Q_uhNkN)1DZ?I^3tp!v3F?q#B}b3{OuW>>d`qcW;PZtr@Mh zkkqExFs*CC1or@>PyR7^VBHeB*KriQ1ausxh2pk2hQ+VJ5#wT_oXrA9msUsG$aMTw z&Bka#Dwc$EvP@{zqZ0Xpmx1By!(Ew_SNOpYbp4T)a!>RqWOKZ7@QJ;!GPkU3UAC;u zZ$_}RFV_;p%3jIrklrWfr z(RIq;jmyn&s8^SIb5}Uzx9V-dpTU!bMI`1ZA~Au8M43lqs4H$MIdMsaUI1wy&SI=up;!l!`2wI2nh37!i_ z#>k;a3vFa7zMj?JJK(_BP^F6d9?ZZ)0>G{RfA+owFpjG_TdRj<$Bu0|wnIpQCk`et z_GsTP1;@KuuceLkaI}&g#|h5t?yR)YYFFNe6y-s(ddJ~eXekYCnnHO~pcHU`78Qqw zL-`ABp)Ic(N=y0MQYb%AXrcdi?wy&P*`1YSTOuJSE%NT2*?aHYx#!+<&-u=G81_L( zjUYcu!3v5_kbq=lYkmTNyb;71LD_&}8aJS2@4044(m z_zmEFObP=vfp;2-J@Y#n>>kKW$# zcME;5`J14-e@rlLVU=TI5Jbh?f0P!fbMKXe9tHMCsTYtCQAyW!HmC$i$&+Dv)oi1$d*N+`*}WqaR(nLxXc1;-fhs|qxGxiZ34D2U7x9K;`kg?r!5E@#@E%K5*c;dONzztQ~mhSypCv+iK!`Ja8C-Cx?e{Qw>I z^Q8j{2*8QM{_JgYecQX8D4%SeaMRhee!3SN0XRQvL8$ZnvnQ1#ApxS-z?hrqEOp+ibZZNjnC{izJH{P4sc z!YCeB$re(`oqJavrjraJ&A}%CjRG+wAmYiI=?7(y8)XR@%ZP)h9s3Ha9MRG&YX~Y= zvxR`VB9FXktZq@MTco#V-HfO@=aXMnAIR@Fm-sT180w1io{@L#B5i4HMEybIzr~2lSv$yUH)2l3< zF7@&Rg44~V)6*hFsK$zzySV9P&LpPv&FoCTpEPDRyQotF4YbqHXomPD6!3HwL7hQWZRyY zZ;xbGKE%`ylAD$I_xQ9D@1FT>GcVe~UeAfrRSKE5IGLZ>M`XLhV6ugxiQeT!o8+?D zq?ps=2ML?;TE!r7_Iz+|)G+o$`a_-Jt}da!_s}7sGaTuG*+fD_Sa-&pZi|Q<9zW3h*&{Dsh#vU2Up)T6f12>^ z>K@#%Q!2YKQNka^8%DmEv~Z+6NVvDWB`W|KPDfb2qHfFsQIu&La}Q`IE=yZh#t3z; z&d$6#{DI6y;vZQ_e47*NB4tfA9R&)Wa(Ex(^UcdMOr=qZE4UY))*(ssB|`qRbo5? zZii8EgzU_N(ju$H?rGopnJX5eq2s^t>P^45wpu{{11&H-XKhGW;{Y)UY$Gh;29kwh z8C$(n8*8gY7017tVF#;XK_28`{BYDQ&uCX+gj3HAe6_&#rAg9qGjq(pXy!VeN&AM= zt#z zC+BkLY(IE{~0|DEZ3blnbqRNFJztS|xQTOPXx$GW(f8cK^k zKZs!bNEYu(y3|5-;h4QwB^(J`!V|M6^+p8c zx>_j_**ioB=mpKV^VHQS44$}xFaf74BeEk)KTwW^i8kRd$lB?Qm(0na9Iiy0j42CYf_02u(~aVt2Zh<9;9IqNw9uk(0q4!>sjK%Y-3 zq+8@P0zM(o8I5iJmoIJ!-1>Eg^x(B$vAo-O{x^AIyesaELBCHa$DM&5#-=88>R1eg zU`prsgJoBF2K-(*0%-@GAj-6ZPGm_|j^%r|b>oC4R^Z(8ydzlyByH!spa{b*RTwHQ zW~wkaeF>Kj1nVFm1eICYqIOBb05khwwg8q$@)t0cKbq;>D- zWak*o0*(WoNs#cL`#6jw#7U;v%ye&iNvUw#7n6!>U+Qy=6}}iaxU>IHUe)%U)sza| z^Hxhn)L;TwlMEH`Y``(-F&}2MO_xYN2+Fb3^SiF{?}B0SAg55RpL)1uI*K?l<}j7T zSUi?+#QlkcH{sGs&2|J3&eq5j83c(8p?M4BA_gc4`RxnB;ZWp|y41t53`_65+{-yq zphaF%e?vZB`i+Pr;z=aZtTym=_XmO>fAu#oiv#;leEOx=-t~~>UB(q&>o;a!)wg#(*q? zS3W>a@sWb&S*ew>IRp;FvOfp<*X%>{FWSyHHlriV2wp!GEp42=ni;@H0Vj&PUEtJp zdVEQTQf4;e-N>PCW+e3)|i)r>TexQ)0_t! ztdQ3fo6xbaNI^CtINtp}Yc==f(XPO4Eg$*}V8#L0I}d*03xlt$ocBuK&1OBN9cn$= zRi4-wZTN{zflTZ+O?TmJxrRCw*C{oJauWhQhkG ze|#qm21-6Y#m88V;+Y5LuUB@R2bgb??K*L7off?|Tf*)0Ig-v;Oe?LHL77Zm`q{89EN|a|MG?^!tx~I0C;+Ou+-=7I z6fo>REdJlJyY9-S4L@n#*J#DZ75Q)0JyYbM_2Yv#&D}F|kW;ODOU;TMvUzg$MU%&P zV8HAPrsiDJA?G=&OdFmEK_i%DlC*qgMEtx|sU;K%_xU>Y{x zOX3H-9;e;yhoBH4$tkrH3Ne51x+8c0Mf?W~1J0hOo*er|^Vf_zuzq~ZmZQ+25WR~u zIbhRxVFVQ~Yr!k*#$CR3gS`C8SfN8Jpgq*EZY;I`uQFzzMxRheG_CQR$A_fCO?fII ztp3b>XWWV~cxwwo0_iU7oPYwkPzNb_Yr_XA)4=HsvZ zzrVN8|Fh69?t0x9n?AWV_oehH3YjqYD1Q~_e&-q2cD4~LvJb>vb_p2~JuX{JT4d@w z0BT!o>Khh0+OII-X(2z}*-N7pUl`hpn>2hNN2%C7iXQ$1N#az z+zH)cpH~lwq{kp>5dM(_KwpzEQ`0W6Lek*()mquVcvZwT>2#yldhT$!nlgt4`z{-^%^ z!R(*jv@r1E)~|l(cfZ!ywKnyiCsUu!{|)v3TetD;%{Sqnwg1*e;MZsb=I390X4_8Z zHN;+dL+KQ^|4wh1+%pp$8%-eeQ}id}ad#{(*^qRX7bR0^m}i(thsCGZ+!UYU_O`jq zA#npN$4#3MLK3n;toXq1=g1@^NJ-QKOf_sYu^8zza79XpQ5YOTPRt>gW(2q|hUG$x z6sJM3K&q=e`q7Fki#X}3E*huR=C<-=I%1r+BdYC)tQ`@VR+V5RqD0ZX{uZ6XDF6m}9vm>dK z8wYm6IH76o`)5%ADjZ6kp6RJ3?HgPDB(!80w| zI>G%!7OWG_*^^3OR@@P{$w|8tt|B`xQil?zUmnNi?6N+tp!GRO4 zptNQIwNlZzXdpN#hE@@rgH{p4My;|?TWXauw4zmn^{cIlFrXCxeV|qm;RdiCwF*=O zYqfgS2o5Z?{m1LS{>C5g3&i*D|I6Wjd_~N-Xz+o;B&+gB-L6q>n{izPk#!a+X3Y2s zg9E5ea}Zx5(}l^vq1F|!_-czr8JTbPq{hWV<1Uc(FOt7n@)3aSQnBunxDLTNfR%zm z+bSq9oOZ$GatSx{Wte_hD;)P%W$i#5KNvoMZXm+~5)l^wq9s{pvmBz6L1LRhA{4_q zgS4pR^~Q~g4;Bj?bNs(t$%sqGVU$*vainl2xa@wRJv$BnVJD8CniI)HSSnT- zw-w$>Ub)CB7nRD{BBE9fgfr@fUV^$!*OFVdu6xzlkA5Z)-?8iK|N8g!x2&xtl~F!x zYY8O$6hY*%kx`r-K~+3eF*+4E7rs8M5C*@79-fsX7t4WX<13KoI+vRcTXUj@RNHBV$OXvxAhohb9 zv4ZqbwV6v!2%vP=TqFiyZfJb%m;Ugnc;Mh8+(f7J?$#EQkntO>*~Q6L6_Odz&R zb#s9@sR_hQdfr(rB>$JI8^bG`hK3@Fs&u{qOz?}_m3V-? zA8mhNg+*d5bbjiy=#~Y^2x&Q4p2QV(`+Py-# zW1^kmXc*Mvy*;2x2@2sZWXU)bJRuwj_XUrxuz>Ifs39STKJoouJh<+gkH0Q(R|#@* z)t{}rguvuzx^JxU|1)&)DmhOsS4ztK{|zsx+w|myv2{HSFR?h5bpOttICEfoXfFWq zd!ve6HJ5hH>`lc-0f-+I`8*UIE-7ZWc^t`@!!z?>=>aeZ%)H`JL1E$FF`@7XC`14` znWx7Toe5hK%w`_1&o3e7SuNMjG6+I*i1wO+|D5-YF;2pM(vM6DaIpeI17Q3}wg@i} z2;as*V+Cw^VF)qKaJI(N5(|t&Xb`a@UwrVt+iGXQ{~nLsZ3uJD%kg3kVRu^e|HDt; z^|4Pr6*xFJ-u!zfez^W#qbTYg*X*FLM*a6GLnV;a*x>D>`uHOh{i%8F43!yLQ;BhxKPg$z2J4PCP^fX$Cg&;~WxvhMe5B969ky?wCvRIz7plzhZWo$O)r(ar!SpP8^pkCyvGCaO_C%K#)C^abiNz`ON0V|s;X>-Jr3AcAy za$;|D=!n;K`$?A!KN3*Jm$IRx`EM_3M+toT->&}G_iYUX-~Z9P_@i~JCMn8uRc|R> z?Q2`gCFSuk=LXR0wHk)Ps<2yCME?V7ak*(nbX&^FGk0=P36(ZzqB7G`Ar7K!v&Cg! z+>Nk9U&S@^Ed}|nbV)~aqHyiO85C2RdRF?jY@uxCy|i6 zNm(t_j`kcT>FBrNRD?s2PCC8)AeZM6^2a%W#|^@rlx#>A?u;BIq7sRn>-jiR4hB?S z0J1AzO!L4Q9FRf%mjkC60h+>x`UGHVg&0`Lfx8BzlE7c!_Lt+Z6DVx)2)Ciif#U?q zRtP3WQW=;Lpy?2k2__e;2||%lOcl}-Xo~Q%ta4;pB7ird)$joc8UUuEItZeMWK4um z1I3DjFdkH^*HhK;z+uk7An)J|@}P;gDGc&{P8{#s6Z5L%@(J~lUoBB@F4N6B#QWKp ziT8tMncb$ZQ?1J9s;nxemS~qGr*cnBZO$K4D^$7c{gPS_ax6^%OQsRfkofg?2KK%4 z$L~D2cVpnhmOmCZA8RZc51s00Ku)V55BtNuhcPYu|I8J!ttE(Jqf@$OzL!!bI2= z0V&1809bZbhuAE$5E*}R;q2svr{*u5{o@N~-+tljyV!@fTsZst7tVg*!r4E#aCZ8_ z*|QhUme>c}^W=rIZ)Eq(U3dzY9=q_=BNxv8&V{q@y>Rv|7oK{hh6;oKZ?0)}ob!kc z4l66Kfk#YAB%H}aEar{-WO|?CXu4|MMMU~V@Q6i`_(U3ESv`nerjYv7$Ct|}=Cmq| zVp#EgHowX8079|IFD!fB^zRP_Tz^A0)1HEHc~G9gY;`CzaFrJaV4kt=m)8r`@U+G! z*0%fkxFV>b;zWG|B`=egtr|)mG+eX^*G6|=7N6Mc$m|%;)Nov%U1#ceMFt%aNqT|V zcDuYDhqvNdwPf0fU92Lzj;axLWV3@%FG6rZ#|FCn@-F)xD3 zJaN$m(j%YUZuk3RiRvx>P&g1db@h9m{*OlkLTKZKZ~WDx6*64$)Mm2W9!2hSP|p(U zX4Q`0AtOCWW};fE4;hX!m%o$F8{fC;a!-p#Vzu5<- z-8&Bwj;3^N=|)Aj%$H72P0;#Hf=`Pi2$AD{ug{L{%q{6JRLGf!82cUGHn+}9jnloG zo$j4?o*X!O2-!pK7EU592zIW!!3YzBl`&&)Gj3=C*8X!J9z;SmF#I1vq#|O#KzbLI zbCkwS6~)DNJJmU_QkWhja{U9xBZtIjIK-W%Hk-?3zOS7mcWGPTh5s<(+z|Y1i%}@` zk8dWIw2_JJ7&KhuD(a(+bIm(hmcG(Hh5fL8+B(@iy8)~@gWv>FDX`1 zFQjOAA4Pq;;0^W2vg~m?6Un6hLe={qYYTGd8Q+JhTa@3&P&Phvx6qZ!6z>y`$T=_& zUXH4!7o1R!Um8mNWA>2$ZvkOQ*F>&ef7S z-GT@`2)TFhu0=~c#)|r zf*@E2D$&VeuL@`og8f~=p8iNkQz&pQ%qUogIAv)@eDHLv-^M=0g#55BwIxQp>#n<)=Hp`b8uMAIB-^HRtn zkHD9KTt?+fs*$V1;0mvO9Oje)_`L~jJ{^c_KRAA~I_G0NE$Xg5AJ^`RbsU}_aa~yQU_@>h82YNQ)(&F z{rI$CvuWk2RR|rtd_O#+NO;!h6yhU!hc|#ZugH;bGfKo_Ud}nZdofUIL?qF(uwa*t z>Ekd6Bl-2l6JR%yb2S-fPTQt?Ip9(rBJs zgE&$Ii%7!;1R;A*LJaKTAS#N-LBuW~n+(!JceAW8#AhVjY=AEAg}RJm46Fq=f9sJq z7lvS?gG&$=t8YE>yL7!NEt!A zh_cg6$wbCY49KPik|#QXDd(@eI%)--bq*^PyB+mZKo6Fi!3OArB2*ck!=lC_rHmyS zS%DR)1_F6W3)&?ikh7E{0)u#p6M5kY%%C`4`ld{S;Kxq zTS^=JJFY?^`{`R+rfwPp4?tc7l7o{FiAafVbAx(W^0<5z*D7H^fc$`h+1X}O5!kaY zeDr<Bs3zAH*hUbM%237_37c^xjN@lqw_lg;1H*v%^m&fRq4 zb~^720kKV+K~9Jw^RdvCB}P!EgNUAZdHxo-)Uf`rbto-^-UdMpk-1l#Y24|)mijq3 z8De9+Vd|lhefn;>$had!V-)%*18%1A!$hcMINt4@vKBvMcGZ*$h{z7WqXv zA;JRyW~eI{u=3#A%L`b>(LV;aM{3#xF&ewhQncsTd+YkQl zn_hGMtzWv?s5cr$!)(D0N4tYUBr^spHZ0f*n8wH#aTw7g`pjdh8hN-66>0#n+G^x- zR%zp)t>$9w@h_#NU4sAfa+hkJ^k}7F3tWlwLGFN5%4V$C@oBOWrSRxbP9lW{BTb5- zixQtgp5c8cuspN)M6n~Zg@X$&J)z1P%Qp*wo z6ZVA5?ejY&5NH~%T%?@RoK5BPVC13|iBdr*S*K#iN(I4UDO+GDg_>3vLjHIGC@tcv zx@a+_Rfabt>Y4%X9dAa|wIM2P=meDS`Xr*iefLL(Z#f&-z#@|?v?;?ttcfTRF?rq3 zSrJ_pj^Og*Xdq0El5cx(A2a9&m555Wp3!0gF8u5`h$9`uBxLhB*glKny2!6woH%K` z7AIJ>LQfVZ3IGRg8vqSbDA?E48x@X*&%G{qI1=s>x_a*fEs|c6)W&OazwmlRUT@xd z48TaySaxIiQOvWxheHc>xBv6u9~`@8A^HU66|@@nIkgYU0GNr9`C}Tlx^TRRd{R05 zyy8R>4xvoj>mqu!#?Y1;khaDH^GoD`!OJ1Wi}sS2ClxD&OQ%_6z=r87Tc&Q$r$%!r zrh$omFHRcZWpz0nzH;%!iAywcv@aqIu{>dU8CX9=6cdCOxx!eu@X!RdhXh3vla&c7 zFg_w}5p4G2Q7N8cdH(=822&f-Ad2lsYlRJpPc4l@k@QH`KNiTzR7NHtyw9v{(6O?% zNquAui@aggyoCb_S{&sqGGfIHZxL!bT0|f(CSL5)njUjGXz2pD0 z5P*EiF`h=nO)=omi=kPKh)s6>xBN@prdO~3yQVwv;bDIMpWQLnqNFLmMom*5ZJDy0 zq#+l5kS+AeyJ!zNS4kScR+G3R#D;i*M0*V)?4sr{^oZx2Db46}4 z9WL!t5)Gd$g{Mz4Fkl{h&JH4v1x(mw_b6q?aRtvkpaMW@)JQaZgq9`v8ioA1Kg=O5 z@(`jaazaW7r67sI;qH(Cx2p0j8ZvlPsJ&J|G})SGb6SU$s>Hmc)g%IILN$rWk+_JO zlyCWXoPph{9g@*-pnL9)S9@NwKH%u^eJV8kTFZ-!Bd$EA*+4Uh23w@c7~;!a%cwcD zRb%N=#sD|0z`|t`Sx|nWYHx}<{>WpgjEOY|XBF{$=OkDoG~<_f%z>@d_iL84xYnww z4l=Zp2j>bL2Ao%5!1dG308LfFfL*?%PqtxM^Y|HVN(aKNl0O0vc-w5|P@Pa(8VMd- zahQ~@KSoe+Jn4!_lE))@6ZSYj!ErklH=kFOy>^ciQJ6`mBUUYy1Pac6_J=p#_wImj zm?0Z2*BPafAQZYr&7`w^4HdkG3Z_)%wVWTo?l|W1e7~CvO-jr{RX?qF5hguux7+24 z#V~PAU4)d^1(opd@lgp9+0)e9Pu0H6Cnl9dJ^ z2Wh(qJxr$rz2huS2H9^t@_O7ih&V$sk|%MDz^xfCB;ocVQXo(^ z;~_adoEIJxPCz?hmTUcK-ORU$vjF+gP?reHG<960j*Ix7;2jq=+r5;=(LwDv!!46D zv24u-k`Enc#|!E-`72Z9PNQ7OO@L20zaUK?j_gv7o4p;T&dBzSf3@pBzx|qkc=9JV zU3G83a;e<3Lt$$;L2ux(%ax z*F>a$&0TZ#gJ+z;BKRE1q?kasjOdEX2@x?fF45z~?io)cVhMNBe4l*D@9a;$_Kv`H zH$L=T|Ns4Zr5vp7lLGVrs0Y>hEQUsn+*#Wv7vCr8{BLRe&AP_ltp9ZVrz?E_y01?h z{q0Ad==$wP@Smlz?i1J5)on>O*d*yweU{0q@c-*9^$qp)vGJ!H`SOFfDjEX|Ge zjq$Xc_>`Al*vu}}H?3<-U=veI*IAky8tU`$r-PObOR0^78Y_inXqwQu({^_t~y=8JE`=k73z4C8;BL($8 zy~AR$Twy8QY`I7Kfc`XD=+71Or*t#@ZD^#>f~T*+O~(I94$EGP%~*zSyckV2S?bqY zF7w}#L#be|@^8~RyjbM_db-!L&vK__hh-~RVx7WwJ@eDJo>;5B0W)-^QJflw{Sov5*?zCJnfbie*R*EeCT8!V$w z2ei?rH{Z~hgPG!Kn#oNGN|908m}nhs+7Ve3=-LD*;ln&mS)9Dsob=#vA&7X)v4d>E$i|U*e@p3 zf`w>9n|EBbZEMSp9eC=` zD?_#!pFaZGEPU<;Wd!QiQNpa0q!gg?CZ-}P-|?u8DM{v+^{s8v`#qGKwTGt4)yaeg zAmdVw-J_0h13(^X3r&_Q6r~edyHbcZ*Z{+~dJCSXW$VtXuiCzO$8W`7N$kE~+&%QRjn5MxMoA{Ro z`qHqDGjpErvAmQ`zAMniR`#h`nT+-LxAZbR42jK4*ICvz;FIzPtHQd5dh`V|v5`J+ zRi+S$ISCVPZEkMX?l1q6F7b*QnpmjP`EE-DZI?RvFPkIy7qvFy#^w!>=<_c0V{#ks z{5p&Fj2OMt`83`E9+eLd32altHZ4q);4;Mw@X6;T+@^G_p&41Tp_0o=z3VKP4Uj)t zLh-SQ$vdvGcT4p)G^~TQ4FJRQr**Y7z{T>+CKTwVOT#)W(b?3!=kG*0tvU70Y4D&R zG>i3-oB zU!wKs7Ob^bXy4Z1(?<3Uqi-o~N1OC|tNz?VWjp8(=1$dB_KS7eg^k)Lb^%kNp@AL= z|KT)vUPkwn*I92FJAVRSb}fV9lXFkOjQ+20*)>*~u%VF>ctP zEl1}wmMz+|TCj(f#>+2a3;mjUX!>V8yHJl88evuQ{bZelJv3KfWy;*4oua9c7C%-> zKZ9(LGwqpc^iP^Oe_a2hP4!LLm^7F@A7-WWgqXo-C3n6TC0r~p(#k$YbME|o>{<5E zYLS9iH(Jz9(4xt5bHg5drYVV6-_W4m(6A1enuL^4TZ3pcpriGc0xMC(v!Q-8uY70f z2i8TP+#mqF=Okq`gRw6T%M+}de2|L6=l7v&n=rAwmaFlpBr2W2s=p59XsmhNrgB-+ z75L2dag=-UnM4&GZn_$R$5tP#51D7mf;72Bxrw$BTBX$>uWhM{=w znL3Q9?uLd&f;H=eg2t74eAs%#X1N}k$iins_nDR_wlFKIOjWj+aRQwmLtbAYj z6Uk0xr5lW8Bt`XXVQ6Ti744ZOJd>g()~{npdh^dTpbW2^UO(o|#fUv_XUYcq0~x_s zHqzYVA88t5323a}p$#o|r1B4ppYSwFbyx}X72_Ei=^3zr)eq*Mc~Qk%S&!81`_(h21^ywiB(2h>rZB^mn>w5N(W zOO?__Z~U*i#CV-XjQ+zr##EvI@P669{Igo8dR4oG4_KqvSN$*a*NvZ{nQ8r_&4tEx zd4K4IuFlQN?E&^peGgcN*dOdV`U~u9#m(h5$~RX$ky%ycpP7APZItU{w=CYcSuGb; z#yZK`t?0c{3&(Gre-LwBU3M(>_e;=$u4g)rqR_6pUfE#k*WuKHo${F*@Cz(x4KI9I zso}-f?G$!hwS7m+wios9-n6rHMawov%aN@w*mBjjojZe9Z`peFmSY_|O1Ey?QM!Kn z3$NOK^$lACTX%1}YNln!^>qGksw>o8xp~9)n(G?f__)}AGqL#*j{7`a$|?}~T`iLx z@(7}CG-L|k=d)K&iX7B08$kWDnoN1c|hD=c3Fp@w3vQuzD3ulZ zkhM8?ix3=>(%H;@;i#O+waPsSmQ&Q32skskisvN6x1}p262|Fb1Ny z8+H^}LLtOJ6e2PxI3kmg&Cr;NN?m@M1a%AyBZE3u0E<#1hHfdy_r=G~8nJ@0B1{a0 z6k!iX5OPb#=G|=%lmT$`CV+pNxp(d!&`V<~->$@!)lVNWi7WHRy!M#gA;;`4e??qb z^<)P23_K5&@H5U|+mVyO&yY-Kv&ghfL70RXHN1Cq4X-snDJ+L#Tm^(rrvMAq!stvG(-6`umMa0IfK`HjDei_Ufnvog0Ut@Vas}eF z;NNxr*@yo4OM(4uz0b7&(HASHy7q8plbnY&A7!Y1;V`A{El*>tyq6iq%!e8^nm_?7 zhGI1*@$*8Pi6PQ!qBSp#j1&uj!R#2q=rv8HmR>`2wKWu*%-qYjd#}fC@Ia|WNl@kn z>UkueV@M+aa3a`CFxL8bVzvt4lCm4 z-hmz&Wae2) z)S-;ks>;!?ZajdB|IgQLx_QIFrn@cqy1vDZ|I4{HbNBQsIHZ3-f%IFZ2U?~qmH2ki zA48CO(k(lazNH}jfZ{=?@>Vk7s;q$o>GuKBk1U=X(;p`6TxT{DANtg*X412rT*H$z z=76AyhL^xGMM`*Gk|XJ^(1VN;j?`^79|7SV#^Z__)vsuH@UbDdHkkqyFH#LKz&=43 zgw$MeX2;GBkxoxnmwMSQY?(eVdE@l;Y-0dVLOh!$qJByAfhQs9_SwL@>#V$3(J7$w zZEa3ZtxY+I+=g+0{^F@~A4DHA;Oj0FbIbYWV0W4ucd2jK!RrudCY zi)42=0d~cSld)dy6|90Cq(L`#oqKOamV|R3&EO=uw+3C(Dy95dDdPzb$zN8yZ!J4Z zA|(%I6Rm*5LiDpZT+Y3GX1gNkTS^^^N_yPpx7ppG6md9#n8ke6Ed!>Kj!+!q@}p80 z^|7QU2y0dOH^wNlNm_`dvy>PGQ$Kd@qj`KxK&-J>L-uiX1c_3>I0!~FjmMZ&jf$zE zN;#en_oEFJCp?xF(T2#|0DPa1JN%&Q!SJZ$q|n;OSXf(=H|o57rekD%>VtUs$E;WP5gRb1J*TT^!KHdA)o zUYAq$#u9dq$5E*XnaQ`yLj*w-5GUG<&J9i3AytP3FVe0B_6{jCnB6aQ6k$6AX^&>~ z1T0I5qFinmVhCgH-jA|2uI zhq!S2XSQ)(FRA2JcCrnV&Y2yjN5TD7gsmS2BN;p|Nx#gCs%JHF8zYZ}`K%sb01Sa> zzA^j=6or$MPRH>gjQs6I@J$yALZ>Vxw3G121lyeC*3;<((?X>p=igMLNbPPbXHpaG z&^1{qWK>E=WmJkiiq$Cs2AarM8<2tn3%6{%_d8!o{$(I8dN+M-Zop|&Jo!Une5xk* z?L}C4^W>#foQt@rY#a>|6cd3vCSJMV0PfUgbZ=ZH--V$C)v&*ac4;y!sA2^sugT_P z_M|n`OT%m8FD{+R4431B&`DLxL@afsmg%$$E|*KV`6zpG`eiLO^Lb&_y8UPrd0fDc zx1=qLJAp!3$gu8SqaW`$jIBaDlH4nDq}>R)X7T@ZkJVkdW&P(G^Z4+JMbG%~|7Vuv z|92<-vDoa3rmp88fDwQIW)Y69uy*b##aT$+?Dnbl?S7)NKUs3lCFX8ZU;+CkE!;Xi z4O-vnCWY2FZbSAekJIUo$w@O>U(oHrOn~G9HizlXsRiQ+(E@;}<8Z;W3H{*hfJ&Up zBCHL0{RWGvG-B#tJ|M(2X8_I1_i>s!jokyhb2e=uB0X7U++-T`qMX3sUE@tN;ts4s zO3NZ|nd0Yo%j}bUA1AEMGs`yu?^w%KN;L5a|M(R@{p#*79{lz@KmPM0-+xoxhmFhC z8lf;JojNYb(*pF&iBtnlw=oTX;6`KB)gc|Tb=B}?M7@o)C#xc zj8|PXY8WK_-Zp1V6v1)I2s)81B2g&3Q6RA#&Sa6WGX_%*i^V0i0X!h2d%((ZlzAOV zITIFlwqZBZ01jQ^}HK&n_<)%pq0Ly^-BGr$ck+;#frXTI{(kLo^Tl=!OQ zGH4QtH#fx7i>N3lg}xVemKBy?0*1(B2v=BVi56pEVg`F)KX_L0?v2ll#;Vm8W&9K+ z6EBsF8JKe5rN;fLuHwS!%mESvSjM29^x)l<&11L?1{3%}+IIWxb{6yvj}Eh)A#kg; zhMmm2B(3-*5LP}5R_<9#5a;Sunfbt6r?RfNOWE?eGJU#A z6hsfeg);ugf7vwaMwfs?*rd^vAgb1*47tb z;RpiC;_iJ8Ae+)sOin|-e}&c;&ywrQvkGEdxCLs z6V^zuup2)4XOI1P>XU&(b?<%m69bReeb6ZC6;FtLt;*=J3|N@@AozKODKETgraZ%7 zq2U#Fzd*8zTpZG^MT>ZBTk+aCL zG5MQD5mQ^IF)))alSeY*Yua)SnfweuNkLWhEvzTdd=GOVpc9wDQWa)ZE zv1)Fa+L6kOX)toigE+2;9x(DJy*4M78;~iMFX&$#c!mI;AXTcSHg)d3WD$`D&%F&M zR6$M_QaRz=djS9+E}nb8ASLs|snJ48eQ_yfXKhX8t$C}~6|f4yT5Qdycuk-lPlLsd zYC;AIswjc<#k`&>OG+dfIBFYx^*8!IwBUYq-QFJzZ>zt$;!WwE%`k$>kt!0G$@UAF zBR5u-UkUUC!CkAi-u+71Djs@he)D`g zcVCo>lPP5iBP|K|u2@om@3|Ik?r-#VESndeGClV>e9}g2D-6}&*DWD8a zd5{jLQv{#QaFk_sh*X;U=~-{djSp#|F`(XxthZvhw;&8diV>OaP`vx-E!`?(QMp8uGlQyeX>xXP1HLAORk0VwGkr0c1S|_Sc?pwJJJ8nx?*?HsLvBl$aIzys z!W%(Ea3nVV)Y!lwRY0`Li9US)d~o}L8wrJ%pHQH_VNP(Ilas|k8KlFugxih459FHh zxj}5KmRBzgWkTa>fBkWaOcr`zvmjeQJEf9n0}U?Hb5b&&xReLP3ORAu)nIZER2yLb zlMul)k^E z1{S8XzjX{${FILzGMk%F=yn~5d-8Z~cHd$E;f4LXzft$ak6gWQ+omr+DSi7Vm7=N} z9W!|y=-~sgq`GDe`yQXwn*+KQ*xmYZb zbS0g3o0M==d*_(u2VlI*j>r*H@7z&2JBmFoKT;eVL|jx}0RNF7t$hiC0@e5tmG zdnlcr(qfegNzS;^n|<%U?ZXE@@Yt6@iFSAWdgI2n=8Ri&#&M7umYYihv(>_&UaT{Y z`~Tlmx9NuUw>9SK-ekFPQUCwtUYt8VGsu&6$fX@D)s1DkdGdxCXEK(8MH{EngqZLG zn(Ch$n34IN@zPbb?(`>nu4B+9ZyV?d3mw6( zW5|Ic3f;W}J^lFG*B6N*#yAq{jC2Hh^lJ;6BZb<^`;3h>E{$51Ts9&SROOLt!%FeT zP^9lIW@K?tqF7{e;{Zh#zpnVL#`M@i^tkIi@B8szS77SO4`;T!9&V4o`#@udt7Q%N zqQWpaj^r{B?aF|x%>G%^u8v1V3r1&MAvKzBRo@4$s;)V^=(E|xP_U~@q!GHAe|I?C zqTA_k(P=^T&JE;c;UYYAKKoL^%g?rl&gQQ|!>SS9Wy)-hhh0_@x{B3CMGhWIg@Q++ z#N}D8+@pNfV_Xw*QUX34pN^3$j1smSCQPcVAPE!d60oI)V9N=2%;8SN?ULPJp8K@~ z+ij{(^!EirCxq@`UnDFX>Fezzv5s_gh5MrI1AQGJ2nhG|knjh4BEgH6Y#eUm6L6$K zn-_<3*`eBUJ@BJRq`9ev>r;c)M92s9)++8ycd1T8^d@3HWH;Yhfre;{<^ z#6^qsIF90Qs*_0@8vi(sA+-g2?h)6>r@p)p-LrnQ<%+A;1ba=eFHMu@4)5pOhTW}h z*C%IU>UMpDZoAftwa=bRcs)sEkaF6W7Hf0Xh~wCsBf)NAcRN0u*bRGmG}3h}9PRJx zg?x7gv3J9Nw_oV(j2N;}qP?XR@$pm|*0vEbhJPnux<)<=%7C29))w!5FQ|L_r{1#= z_1^R`>%Sde6Yn+g{?!$4M@D3%pqJ^fG=$*n;yj{ znAi`)UYA0=5dUyoj;U&ZlwfJ2342K$YR#mrO3}nY5GWbjt4_($(-pYQ`sK}U_?|zo z^}6uqKECfa$1BZx>?twKRSqjwcTX2CmCxrrGKCzFuUKdQR{d1$-evfMiA))_ns|e& zpBDG6fInC}n**^(wpchT%TH%KnKL7-GSUiq);e5%bI5r=BBv=os5z#_{~XUMH+TK) z1KV%+UJn;i6OLH+=p*-@EX`&n@&VL_Yd*_rWov=$JmcnIJ{WgQSv>9b==J%8v*~wfwMU zDWg#+i=8T7M-BOBmqx`b-E=xMwf7}%_mS}xKZIs zM0c@Lz}E@zCIK8|T6mC)Imf>sq!V$f2ChE@tv)z=|BhZae7ut_QxEe^inwStBy&&# zM?nCBAIs$B0Xe+rm;I7M@-qH2vm2^+F9@Qq&2D~74HIc4YR?ek0zz!zvn4T0N@F>> zc;9}3)=rr?QL=D)C5muok>8hiljsNOZ$0uR4o(oTktN_A2I(2_+W2tporJ6yWDHCD z1@t^FeDd8wh&h-)`7xL|u}?Z%9iF|a;L<8wep)EY#j)084j?HjKpVVStT3Wn07{&k z+=!JeTJf+fy&Tr4M6rBVt#ZId#I%A9p_Y)N8rfnG_XRqSoW9}RNAd^% z`*(_;-}vEwuULP~-Zv&<)job0Pl7pkNSi!DKbt&45V}PLOB}x!wJ3{`y7nA4Ao6NM zP*nG&M%IO@O!j&6*Nb~sV6Qh{c-*Vw$5uJXPA$IRU}fMhSWsSY*`i%3|7Uj1PV8iK zZl&?5lZui$QfisMu`tB*P>8Wa+$YOkx6_yOtA*8q?r#J7%WW>`?I2Ye2K5;-GQz}- zK2dtdB7(m`wKhl$q=Q0dA4C|UUcerS6!Ar7E)O5-6OQ0KiU5#;93RT0h@FMtV&K$_ zVNDnYJ`Af8A`U>$f}BFQiSb7jve~p2d`2%{?KWT@_^c&SwmYnQWZRyYZ;xMAKS;_4 z$*z2esUIXaEAj8~X(e9uW~X{74uTgvY@QxgRIjS{qakVzHSiC)JqBVlKS(Q!&rH#z6_TuuhMDyCMQ-m**r zl1YW6gqI6dLGABEnWlpWk;lVOsj^wt*1)S@4t~D^QfZ=r>z=Gy1y_eenINXx_G-Aa zXk<>QCoDX=iS__tuApfVQiOz3s68penc~;n2c5t#un8fkb(SSx^<{BMqP-TmMhP62 z1(1Z2t&&W~^N=HKZ;V3*_1Tx@`{GqIXeQ#O@|xIZ@F;x_b;6Nz=gAa zaN+Fqg|lZboGq~rxaY|WXWz)~nY-{5EC>u zTexdM{FNl>ZF!h&;=|b(P9nlst6x9bRBvlu))0zn+u9GrF+cFnBkAf5A{q{KzoGHB z20!$l0ozwwc5QNf((+E@U@Dav)^ar*8k>U{rL$rA02yWZw8};5?!a!-c8A((95shu z*U;RQC&dk`voWX{=_^4Kv^ObjTeBmgGA7m>s255125B2e8P#>zYPx0ET0Kjq9=-%1 z1a;+?v}+jk#qxTs4jSSHLi5)us7L!GH-FX>C&`SPWB5d;L-NQz+2{AW$nGK*hpUCb z#j=R|Oi>DlK~g60WCq}a#|8y0k=RFcSbpLR%|J0^`Av&yY+pD?;xsJS{lXZrVDp0l zHYTKmF7qSN8&;1HwP;D8sOChab&40J)_DeRa*wb`0!HHrh<~|t9MsUdX!nb{*0D0N z)=kln3;+7>KMVch6W^Ra`uI;j{Zh+2jPkgKhE%PnK`aB+>f0hOaU7f$;q=W)fEQ^%C`6p^i#yc8{|I4PtJun8`|NAP+ajvA7_xmN}1V0;sVLAIqhcNml)xzWIS(fGh%{Ul`BkhPA^b^`kY1sfA>J7#1r$!r%xN z$BYfoe4-FXQCGhtQs@w`p5TvEJ-ASK_0@ZJUvJ>B?MYyz?+f@(Jz+VU{C4FUp$rLT zZIwypP){@@^ud(J$h~ zb=C}MZOuvyY6(w>3`+F z&fPJSQt?FB*1!|RY>A`?G=DCqBfd1A$UGu9+8;jJ2{1o^fuYWDSCMb6

    b{^^shP#BWV9ybNgTsAdsP_&C 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 z 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

    X|ecBis>^l+UhlAt6(77PrgE?d(G!z`>gQo}U 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

  1. lAhoch83F@FRz-J!hi~PcmX*SoD^e2IPuu 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

    YP6@Gi?=o=Dt4mcQyYLM>wX%af31 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 z za+Xo4a7@{-$q<7RsxfZ;V4IgwTlK?%Dk+Tz%vX$pIl1F`mf@8?I*OsP9#0#2{g1*HBlS#!rO9U+Ud`;d zX^L*yki9i@z#1YlicLu-PJ5Es`170M=;`lW7*&q4LV<3wf%*8bUf;O)F%Wc>hUgVv zxN+&b>SeWfAr>7?W3}@Vt#JyTSTq-RTv(E=T9#y|4_lID^P@#_7UMFFc8cetzTt?4U2N$ zJxsZ&R6$RaN*T;LOO6d>D!qqt>0D@5P(9D>Jv=zG@$1vAp}+J%?>mH;KWTkM)7H!n zju`Dsp_n)F(X^gS8#7OS%h3!(lnt;UgRgK6fwEv+!Jz=zL5=T=4l1}E%3cc-4R(!A zhB9PiD8Lqy;Wr+>iPq0(Y(Km48(`ane z&yS3}#E|7*ddO7CSFV{;t)J46r6U`X&0}X+N*XYne7hm>tVM_umYQRwu=4l+n2 zY2iph%0~BnrQsK#OaW_y#t$#hwX`pUA`DCYo4KYg7Z9u-WRcmPrDMl2usW(ReiJH0p?5hl6=C z0@?`+9hpQb)yRQ7zQGt>ZZ)1c2@N=4c61ag=3+`FVVX%8kE%(icsWvL5b*_%;~TC_ zE8l!&`hKepGoLfxhTaY{b3Fmj#c0Av0ZDUBI#VW{pQHfu#~qA0q4FO1Kk zCY($um64MC00Kou5yQ%8A7{5H>nOmEtzfGrOk~hpIEsmsO7TKGVHm7Odo?>D^v+#B=!n)`QM z|I~FXX@>rl(9c5~A-(gom1!;Y_ax0v&7WiS`049Ij*W0OlhM<~R5Vj4B&U%aiggtx z3^``Mz|>K34h9%>h^V3fNO)1p)d6vnu0oF#7TnO@H%qN_f6vF}hvvJu7kK;4p}qHl z$P5xi9fSU2QICH%JF)b+_8Femz^GpS9C<P+*+`UqB1lE#u*Nt#G3GxBk>v3}cvx4%%U z*S{;T7S*<23xEyloJKEn%iz$6UzxcwehJ=yZCXKh{>+${TN_N(+veG>Q#GB)ri(?q zH6#jgF88IASi(TzCc zxJxY;`vI1oJ#9^+Rh6OHLLj(jX!NX}Oe6uDO2*P(cWCx-l}MLfj&g(WHOA?=xxMJ1 zoo-cndp?eD($2`6Lud(LHH0h}O_xYMpVf=mbf&0}CZ_RCThX5U78iVLI|y#P^H~I}y!Kaz>NT}6#Xbhb8sKKEKDFPc7R--Z>wP_G^VAx+ zkf+WL;XhF4c7y9M&Q%EX^3j-)8oxdv>uxfVK#&wa&oqG(Tw1)QWSVR|rYcAd@b@YF z01P4rn*TZuKiCQ7#WZWvS+6U1id>J@8#0|n#3jgxg#@=;TIr3w$Fvn z>gLL3Euy}y8rHXsl`lXL`C5JbVQYoqpD3o1`c$QouT>jD3;E4u zv1$eL`;M4WHP@Yfd{$j?YbD=96nj30&o?gJ-j_Ogv-_5e zBT!ixb|ksljkNBQ9nv{!_h4RZt-^+Gm?Kb6XSW?sC5nXtu5U*3*#+Ys-kUXnDFwU| zqf0y}G**{Y)9Rq2>V-AEP2VrF$*!vmBX)+7{Tb2-$#4JO`UTLN##$@1W66x{YezJz zr&D?+$`)=khmp!UZW*yhY}Q~u2<2_I4Z0Wd5!wGZg1rBgX`_h#iRkcs3Rk)zSxY&jLFZ1<7dbJn~sTP5MPYfEf~a%YDet-FY>m-0ZW zgZx;^eBS}6m|7UObo97~Y^Xg6Dmf@j3&}~-W2pw{h=MMmIm5PB_ihA@3Hj3Iuh|Sh zl-m1bp}tpNfAIO|Kj``?mvcD!U?(#YA5CX7`?;|Y1X_~6fzx+SnUdsqS+ zPi6D@)MzwWDk#a9$k;){l*1Alm1@h`Xf){xHRI0VzX7KcZA$(6!aO#XFDth=xb#f5 zibrCHMUzIR6iXtYjJ<$N2`O`>-KLk4DJ9r)BMbm{?Q3F(siMbcw@$YT{XKE>!!21z zJFGC4z*Eg=o*i>6IbQ|+*kY^>N-%3aCgsZpxcx#HC<@irl$#lKT&NH!%BQmXKr{g` z>^W@`|3Pf8Ax($&UWD7o$Efv`47}&G9Vt_o=S{$u6y#EIAE_FV2oqxj(IHuTQQhk~OePz2G8lW(~V z6Uju9Yx6yoxORE_qn6&^liqrLdleS-)>}ikDB;M@DaR zoR(L>kwRYAV1xOE0k(mVn!-Min*|WmENQ+>7N?fni1OUQD^88PXGGu2XWz?2)kEgJ zY|?(nr|k#5==_v*Vw}YJm=iPVq$$`Bz>WP$z>Uq0n8<;%$VTg;!g-9PxOiSpA|t5;!ayi{V*c9PG|0~)BSes5oY$`9W+nixUznP{ zJ~1_)<9+<{#Q5A^YH_j?)!mWHV71&eB4Rl>V&zdEA-{<8d>uHr$exIIJLOx|zYVNC z&W;++d>fnZQm^`0O~1cd9-B88w|~&rll{z$OVi#t)U?z{A{I+^$>F>e4hV zx~U%KuD{YoStWOG)6%UjHL5S&&m+G>4Yaa!%beZ5z>qB*J!Bbf(c@jRp<#GSVA!?G zxrquQ(=t_h!7-Hs#v6`Nk)F!S^ zPRveO4k2bIE=^o~#Uqvkfk;_TT{^p?`7pcv(X+>k>xNYK#?8*nkBLpp*i>#h zxA2O`OBLI_Mc1agwFrp@yzknyd3*ajEvi}+`1YZh1t~-`=_6V+^~1SYZ6-H6H$A6K z=4Qs`a@x!s*s+&#^RKvlsuJDXH@VoYeQloup#ERo&eFs=tBJ37X(B?+Otecb=e60X zh0D2F_~Pv3Fso9fVwSQAnnJJU0XCWH=nzxP0+qq+^|%F(z`coY@$mq*MZqy zUTvakR|JCB%|nqGvh&(2LuYqPm4x%qiv?(^eQxmP+|EG$xm?#+8XPrtT3%7$>^ z=nY{io9(`8(Z0C_jVZ=1WBk>&2@<5#?oFEMI?Gf6D z0b6&zI69I1vKYH>MUBCuYYc#$WC7Y}cTB>z*@!pKlL8o0+6J zq#Qw*xp}r{+I)@^*k#VBtY+G+iE9)4z1KMlx4;l(tVGV1Cd1@%E<-)cVm}ACE-ISQkph+f@#W-W*d54|bL-JN9h17`U6STnHd_ z=sr@jQ(fv--(y>9eztwB)560nGC7is$Bz&Mz&mbgWAnMoQ#0B%k(W$xbP?*DSbW6` zo2oLwqEKcW>9# zuB)4EPGwGQ&(f@`M>UJ1Lo|~}cNu%3%bA7COBXLrz1rQqU1ayhJp1@{b$f=!%pAq) z6C-iDsr%N7#!PABxvMj|SIgY(GP}2ilU|p@q+@}G1ZtY*d}=kP+vYc!M9aTR7BV(d z9K8@~T+Pi+yy7{eO6}gD=bTZ@>FukX7Im9M$!sEa6t#_CX1U^wGC%XGXOAkidyAe; zaG!5qp*_#s%crB=32uJr;!Q0FFIZTdLlU|ON0$Th^u(*(9LipvDs*q$bC+LpW_yYT z+VYvhBxp$%y6-RM=MX=!nV+7$`D&+>U1;|vE#a-6;{(;)l&|3R1Y ze+J*7M~v8<5)#Vc1P^6%v$q(mTd#O-snWZ*Y_jXQ(!Rj8oeNBkAqMzIG;rxChMpY3 z(_gB)fCHbumvdv6IigH0%-wv|lT4M{y=l*$WIx%yM2ntrNJ(b0qumdb?2(|sD|53P zRK{}CB9<4L%uQb;>f)>3KB;8=xwY zfScH{i=0*_bF)*gc;2ZxbZ_DmUD{RRD?WQx^{I;t-Z(9M#^qi%J9>mn@!Hhf;yf2% zH`pKMF6L&&Z%y1-xcaJFr^@f%y62oPXSc_Yd)zo$?h%V+y0ialoGamz*K=H4UYWT5 zYF9O($;@c?7ENF8HeSb$np1`*MZ~Fc>-;nn`_y6G@cg^(tDz5f&Zw`4MPWsLB+bE$;TsRzKdaStB z!ZN-j#i!$4@aR?|aUJ82Y`&Pyq?49l)~szCqR6(sPmzu5sREi_pIVw;T|8|UQprLo zS;`iTQpT}yylRN$MH9vJG4u~>xPz<|Emq<1tgo-(^(C63FKL<9E*(Zy+eYW-U?cHT zm^H-cbTm;)>iRRZ^%l`m*{iOX{+jA~_@I8DJZyD6zJ4Kfy-alU8>#D=v27hi(hKIB zsQq@dz((W6w2{c8N1Xty%JL_?j4JgxZLxZ{Qon=xZ5wLl`RZJ05Rg(twO2MitS6oSQdDT znD%~bR1CaERzA@1{EV91hGF2kkIY3m4K;Zb!IB);w0)XO&(rl<9N(+!C7!su>3T^C zu<>W=d9|_G%$4oijPO_Hr~CE%V(E;|(GJzixUJCr_x{2S(b{qpv@8=4?T)ds3W!`s zdHCfhz*g$MYnKq=5?}Bt#mK}ip{-8bp^yEPJLm~t;Q8^x>;bKZz% zQ&wBG*m?ZOtYa%E4%haoc%Re6H*bCw`=)DpZO!3IFGA#Y6JufrrgGk|>m3nSy^^t5 z%dhQk+KbV>Ikx>d95;QWZfznF&nFTILmaC+#=r`LLz_}IC3UAcU!Tc}uIWoM*+Xiy z+dn!|jW(4S)$vkUN)(NhHF=q@sB_~y51X)k6B&)lZ>&a(U(9c&MvI8>vm+Z*%m~;- zq7=&~M*k=p6aR*d!O;KrXv~_$R?qHNd)14D%xI~Qz+CGE6rA^sxkGg?qv(uY^-GS> zzA7v&Fj6;<94S2?kEYY3`e-rv0&d>FIoW+v?QJ&dKg4pPinUHRNQM%2<9Z=h$YKn2 z39CiXJ}xw2x5Z5~bIW)-Q|ifO!;rtCLoEvy$R6VQc<*ST{DGRKSZ_6kEB8kPg9->D z5WDNf2r9ndcv-n(A8F?rDOtHH&1@`noLu+WO{`)4ZyOO zd&5#BKec~GjbbxiFyc`?nzd(Cr;339qGLk?hJ` zoOSDYyAi4B_!9SgOAM`zD-}6Bv{^QtMlqTx#q)*?t>8+nYMxU=lWpiV zAQyDOOVlQt$S(DlALQE0PU(Oa0fatUoOT-Z+BLNP_lEnGze{E8)rT>VM~ zx*z|aEz{@^J?sf_+z&nt1_D#Qf8qUS-nTqg-RE30(YpR%)IWF;pA(PqJmEk1?(tYL zxODM&^rG?LlHWA80V26zMwSr^e2n2%1((4J@~Ixt4S|&#jTc}87qLFr6qny@w(rUZ zZyNG}IkNM;-kynclk5EpmcIYmYOw-_7fTE|6m_5_5(!q=^g?cWZe~KeG(9&zv7qIy z%>k~rPo7@N3tZ(L+^q`!=19R<9RcCDiuYpWrI6e(cGEGjw@#I}ab8>p4-rNTF z!YK|_^a$5u9IuJC z#+08W!5_#MMU>cH;&p8Y9hm3LXFYa(?xt*`8JOPTymC&Oz7`lpIRM`PmEHgeC1ItVp>#fPn^^MhbD_-OXyl&?x zyT8hsy$9^T3oWY*_aA*NN`Cgaeye|bLyQ&QGMoDvgG29pv{cF$^09O*;Z%Ij78h5C zD-A)tXX1%9FOnbRIe0vheQ(>Y5OB(BVQmG-jz+cOP~M9)HU$_E1h?9kYx_3+-sV301Y7VI5gkpeVye)@{ z`Uqy`s@4(Y4Hy)H6C||;JE(xmA}C2=u+&toBVyog*E)iqVpVH;n_3@2J^)Jso`fs` z;25;-4=_iBPaJ-2jMPWvUQcUSll+uRwmi+jyiPn|FHMw!Es${ei-iB zJ3w&JMlDyOD2bAq=tiSA>FG(0g(OHU6dE8!Y4oVu-M4`z8r@(ofWSBJy}6ABxY(ZL z#ZJ{Ec094imGR5WI4?<6%84hLM4Y51cJ@l8V#kiBl0PzwlQ{o)oMn>yzVF`Kw;Sx{ z0+BPR)Puy^=iGai?>px^`}uw!EpjmwVLKg{W1E}YuM@x}MuxF6z-%i}RgK1=_Yb9R z#I@cWJ z{2&9d$6;W*6a4@WvBUAuxu9>RcA+*t^Pws9=OGf+)2Z<&*62p^0^moQw+_<(SQUWY z8Bq_=e#r9g(2iRL1UERa{By~uo{vlEcl#$C9(m0t+$NSU%SaRQ&_HQfqW^xzs9ZtDpX?5Tr(U?d>6=@=u(hJGidQAs< z++k#<#8ID)%vfa1&N-)|13UZ&&Oi?*@0||+X$X9GhmZ5v!5t2iDkHgxgpnwudOG|= z2z_^l|5OFP^~r95W-uO1>AGhy@nRtokK-mP?h6f=!AxPU0KhC*QbZ%ZffKjP<|d9- z@It#%%47Pl!<%DkIswP68nk?&6%lW4YRfb|AV_iz_Tmg$oNDJ_H;#}J&e?}w=P-G{ z)tUAlZoUEpE}KU57N8MJR-48!3%M=-#V_5Qy1?|J`D%eRjy_eW;Tyas59lVlbE+X2n>Fo+IMq$bR%eZW!2%@?=n^C|0d zr5sKHCMt*JMFi`lg{kb6HN}D6a#H&udNvXP=->RjJ36D z85jvvb(umn2ZI4vFOp?A8W+uCYZROJ8|KGYs(;vZ)p7?FU)?5@fW%lV9dq|_uJMNs zPCzDmVGbKO(8kH&(iF79X7GTsd(eHPHiwmFFIGVBJAweJ0-o zN@Wdgy3#rl9LnsNnTK#1#SWr-3#TU~U~*i8dVrRlnapIN8G);BxH!9@UBjdo*a%N{ zd8(JWF$PEIeP=Pu^cvK>YJLL3d`7y-0+6qCeZ(3q~x?d&Z+FCNv zb@}!n!?^rS>gUx}iIb8=bfT2~Ei>Gq?wD>Ha*~-Rj5Yn#k$T_55f3 zTVH+N_!^kD^PfSe1L&hytv)*1zltX!aTgWj0d^tN=$!$hky(W5WEKtj*;Fo3(Vxp{ z_bPG^b@gf7=>X6Z);&wO!bX+{rx(q9%a0nq_Hdz&B)W7AdlE$ruPjVmr4b2^&!17> zO!@a`_HhNd((<8Vzi(A+-wqmDw#k@#Z~g$6=#EKsd204D4Zl>iq!qgYVV=Q#)F*@7 zu#$fC7)a zsX-ErojO3>mvmr(ueUrHj`G$B{C2;V%R^plVsI5Rzm@_fxLlf9TzCdkD~F2yoUUMa zu-;5M@`omtjqR+bho&tQ@W9a_ws zvdehjha;3-YZT`+gacQ37Ft# zYt=FQUvI#k4$K&bX`f%Wykm4^1S{A^6ZbG-{T-Hs!#J)3v=j_4Y{JANjB)Fm=wiu_ zZ&tcUsT9WTL?o6gH6K_iEiEolzOXZAqaNGdrA6~*ONMxV-xBYK%(lApWO@YX18oX( z=vjc8EMzWR!?a^@X?pSgkI{eO{q*9MXR(T~CS2o*{vz-g6R!0Z?5lm;d}ybg8cz)z zji*?~ArwN(yLcJO{u)%uFDx!xgL=ji46V~~!R*`8pTkpW>3DkD2A&~Fyru7l zfd(KR2?~S-Aij%V1-})FkitXVz#Bi__~AJw3b{)`K@kP7_@4dylKtzqehuTx@9y06*qof353I|QGwzoU-0~tJ@ATvyt6W-z93Ge(m={x>M{faWKf7Exc;bsfLR;nT- zwEF=#N>w~b4~X;wAAp9T5?G}w0@da#Q>aPkLuJ4QjMsdiJ27Hxa^vrEx|$dBO_RU?PH z92GN*X6=(aMSTsB>x~Wgymx>WD)_uov$A@30Zxx3;h6RVxFi!LBgoVh$g)tmeG3i+ z918MTJiL-`16NJ!Frrj5xA8)hgo-%_hboIYwg%WGVH?)`2u@j+X+yR_&Q={yiFzyv z2qnTWibRkoJi(N}wrR&j?*jaezj8LxE>Y$E3=b3#QbV=aF7^WVRFF_l4rzvgQNCBb(hLVm1WFYc2M0ml&VfHQ0Eb;gahN`La}xUI^h0M?$M0)L1+isFtba@F-Z1g-mNjQg8!mquP3zOHRVA zuhx&?R3vX5CYH!B*IksP;HToRR_

    Z?Xsb`fEn1apwzoWl3n<{S*#WR$x&Ba=rl% z$XGSZ@6c;eUITXPE=UkmNvf4{>=MP2e&vik|87A60vXUD>)x*g(?!fCI}QfCRaEoK(u)#>C@}v@(9(|8*m`U zYN1V0e0v6-iY%>`jW&IfS`?dcq7+n%BP4fw8l^(VoZ0z%KRU{w5xhN5)mZ#%-ccGB5EPv07`Bl=^%^{T}K| zI6{;JWf}LeYP<9TGl<$QqI<WuPnh9={a^$>6ba8gnL|jl(8f$H=q(& zHxUiBB324_h&~8Bl^J#0C^zFy6b?mIalH}!$35aKs0fX{udMI&ds#T1m(e2cP|1a4 z<+p!~RpwnzMUo7?VWK?=Vw*-harZ4eRawI2zul%iJzlea6`?{i7PMS?P`PzIs0yid z3ZmZo0b(c6WJRE!v^xfgy10UeLQ+S)tH9!aFnN*)DSKR@A#d3oL?s&ryT7?j~sY4+TLjW-0<j`%|Upx^Hw_WO_fhJ*g$Q0vN(6TW~y5FGWN90|SSJM!H?=;TrVaBw)__Xk2J ze8WDUKlJ=_t!qBtbHO7)|Ihn|{rGk?r2c~;L1_&sEjWJm_p=iCSqc2C1b$Wme}W~@ z%Km-YUlrw{y?3z}JF9vlTWk`j`b}17VP@lzyrNOJJyLKdhKDh-(<%>B4#a~GVI`%#7nD6Un%xq@_$)67Z~Wt#Mg+uPrK z=qB6alHe0NZ{&_k5KK(B4~+whnWG&Sle+$?V3yeb1DM5r$w0O1k|*Lb>O3 zJEkm3VrBiCNh>C5(I@)KFo0Bs4V60Q=p?9A>o~V^GQ>I-ddE;2DLZi$LG+5k8U%!h zz#I-!JgKs=_01=E(Ouiv9jRAy-+X-FwOlK07)&B^^nefn%cXCoQ28w^=ZFh>2&Hdk zEn107Nzj>TlrjsG^h(XRg*_E)<8=%oZovR!qqLzHK|B=@Rh}qTa!j{P7uSXiHJG|X z07}9u%1uBGIsBn|JOb8CInZ=~p-K_vySTN05R`+2ZO%IL?G%L2L@ZfoVQ0;w%3Y-) z`8TTdMpt_y@+28YjymT9FV;{-PqU*|X8pCW9zs<=^Z_w`Fo>r}mcDQ4PGM3L$3oSp zu+VnVCyN_8S83NfEOl8js6r%}*3j&I!RjfnKnKmT*erZ=(XA;#T+OkcYf&r|?VM4g zXb36{Cu4uHQ`@K@2(>7R)h%uakO=&>s72CJ-$ToP+r?f;IF?bUU|TjI46+cwQu!8; zaA10^Bet?AlZmc@y^U3@c2-odkJ_kw>>wdNf^>9b(2STPNH!|xsMThjdcszSBdO>) z%iqkf)M9TY*b!EwBsa_?YDx5^soxm4ZC{LRVi+3L*67?*n_fLh(lDM zV$fa&*~zJ+W2EF-A*5JgU)$tz>y~DPbnU3;q4sIhOJ&D&3l*nFAa+HuwhCFt8Wn#n><)NTw7_mj6jTe1 z0=}6OVuW&!8PS44&;xwUjv zuOK$pIa9pjt{HWP{Zgk^c@)8sh*97ihq;qMnv^iM7a@KUOqO!!u0*MOcL+r5A(?x& zlcq;Zkho{0f_lh=W#CtLDkQ&n{P+vULPvt5p(D>9IWcnL`J=~2j=XdH=+P6$M_xKH zvUK9a@!$(bLPuUWbNsol-wy^)zIo>C(PN|UhTeMa`Bz5XchY0RP8>Ua;jz#ENBI0-8JQCIFi3kv6BK(zZv;jlD)mxj_gyqQFU~^>xPwj`dS3Hw zexpLe5_-+H}THnO_=eQM&C z-9Si$eF8*75e-uIgM(m;%Z`R#$aZlM4h&iDj=`C`U)jY8@PiXTr;M8o^e|`85a||! zNu4=gXAmm)J_Y+?02^=EeM3`}a5w2TvJysQsnO6|R9=|37n=lfdixXjWJxU*c+Z>8 z{6sn$6x(#}C@Z2-XwmthPgS66Yt(OFhDT9^DsN(A6TaNo;Vtk0Iuk+R(qgHJS%!4g@7&_oDz3|6QF(8cV&KfP zP3+1f9H?PDhz*4g8sCIV#o@%A4RT2G*QKwGHXXMGMX|7Eeo1dd$8 z_o%{2y!Kb&@bd=ro!8;?(FXKsE&^4iqCmAXYtIE4nVya2i6`~UxRYF5jrStSar(~ZsLY`E*9H7!Q0sCYV{fs?=Qo6K7ZXXw- z1VIe)gjC9q68klpn<~?Tk3(fjjlD9Y6E1`g;un1fHsImGA*3u}ei7`jhVleM_ym!% z#%~IT3keqIl&xgtjc91Us*HVgv|Xe}F-ahv^T>4Lu}uvx=n-~G_{E_GkQ7$=ou@@7 zO(C34-FpiTtW0tIyvwyI$)rxORc^mePhwk*$1B5Ej7;9xckL25=jt_4D+C`0-M3j5n)Wcc@#( z9iCDFDs20+@c1Ngb;U~=9&zs|vwb8zL*;oN3(;yK@)^quc$+CB6;bUFu24t-8Ihwg)ZC!Xm<5QXY4 z$vtW(S2lL`YH-Vvm|tth;gYB~q^<%@uj7)A6`S{en!}ADy;k44|F7KtDJ~P-zKZYi zI6Y9$8%CYlnGbCuhu#8Pb&x1La0+iw72mrK57wp|+=+{=GxSYS0lEt)j@A%-!w`&p zs$-ujH_)-~(b$0K1X`-^Q)eLJ7Syf|hwK$g)%^s8eS_Z1DzpYxn@0P4@EvQtLmwo$ z0@$1O_t{MkSt-Eucpbf~Jsm_V_lU@ZFQC|Wg3ui7NgKGgCx+;D?MdMCEG2SLYW-zefd_yg18x;O~kpr8v%#?Cfw zrPk>)slEEBNCJvdY?jMAe2WOXG=wOzTg3;lMb#>|ahb}VQ>_|zscJ_Q4|-q%LE$?D znETbu6y95v&x4%O2FJJ*@m)Omk{HJ9<{kwSF)uHz>6Jao0ypE(E3USw8wtLN2O8&g z`z!@(zl*10QZIzz8q2?X6dSWXqfMQx)S{`LL=OmiZJ$oT)$&pDV7x-(b)CBF^t;Ys z*D1PA)pdGZ=P}nQbvb?d{h#XVb=ak6i55wsv5?r(8})Vl&IO_m;2Nx#!4Jv=H zNF5^X+(_75+BNXS&-Y#YW`W!!nf{mQfpt9Q-#Rhq;XzZUq5%In^D7KeXm_hs>g_RO z!dUVVTnhE7o)+bHyiLQRYJP$z4byhjsDj?6RvJ=OT|czJ2xNN>{-S!Z{mY3k z=}wC18m*THe$h@P@eDnf3iOl|jOJ8eiRU}^{v*F(#%)j~NzRD#byDP9M@NpDTRvYPF#MuF z3;IV9xRnZekNN_^BgcJ#56(Ov z^o4>Wf!BiXJ?9UdelFw-ghqls-;qFI#5XeBdf69zRSS%UMuvUCkZ8t0I=kQ;a3 z-~TuSc>enCD%8YZd1bV*reklh)(8XFC^8X`Mw97e98WBLK%jIgbM&xelbgRwEvg>h&C=o8!)mLI@bqp`8mM&xuZeL59kN9wd5wH>*n z^C{(gDmadq?MNq_H{;HmwBv}g11ab2Hz_A&-TIU|opWO8mZOV|bk2!xk&!x`c2Z7F z*a_+#dZJ^!wgw!;#pMgjsEjEXiKkzhgDhXzJ+}W{s;^7C1^^nmDJCXDeSfFjbd zO8|+`H#KZBaXqY+c!sN0QLp?S4KB)gf|;uJrXPCqeUY%u20OPcdMeAz)D3$$8nZXXB!8`2HrJFg{lUuJo;Cm z(-0ilQczsSC3yYrcEX1&CH+RTfVKogK>h4y0}7i+n^ZBO0B@yDMh=V(yrQI`p;@DU zPSO<8PP!M{ki_!x^5tsz{%;_0?ILG#|F0mI%Q#nRuIlB>%dIo}ABKiz%$w#SL^OPI zGzaa`T+=`o4N*jgpH8F`v0SlGNJJ*)OZi$Adm9Z6)++%Svso%v8yapsYBPmZ1EwDH zYukE$t=^!U_8QJY@Bdq?=p@z}+G4SY4NM&FpeNY^9NsK2$#GOldIK0kD1~|4^X-@c zp&-*ZKB;uds#G}3*#66qvPYoM5a#Qj9oZ_*zYYCwX%V_)XwX-fLMwXL$qBo zVN%1MKR|d$GB(hccKF5khQt}quqQE?@jzl>PAt5N#E?JI0i+|P6Yiwb#Izf;Xqq}- zXE;Yd#1eNyS($?s67}37!X*>8Iuy2)}EkrWiBw zdORN)&!tnqiUJxW4x6-EHHUq%9oJyVJVgA7fIVY`LTRNIwo~gEC!r|<5_?drAAw-{ z!hR|^G~4p*0N?PV=LubT)6nyV1#F3u2q%s4d^9=%-2O!VYPD7_5V|?ln>JZ18Aagw z;N$_@KZH75->K-Uv{~N14J?H679H?n`j~#jXf0q5g5hH z%VpwNd#eLj%%o?pnP2TEgG2M?=nky;d~}k^X01zD!g{F?)+c}98Y%>b-kh2>2Tf_V28sC zU36=iQo)66`+7e?JZ2ukW5mcAxoB*BJQf?D-_a}RbTu8*P9U!S67_O*CLdM(fwqj+ zidhkaWP>KEu!}-G*D+Vs@;Iv~qm5yVrcKiKwI+Ivx&{gjptYiY?fL2xRqyyAc(+-Y zpEs}V$DxYe->gU+aQ}Ijm`|nBwzVcOg84vygD*X}tqv!LFe{QwC!UsBkuUZqfW>!p z&|p<87E;DU+{hJU$@A4J6mDR(1_%ilo8|$Ai5lu1qrTnv5*eR}>&18?94#agVYHb< zSdUMn!?|$-Z`0#|N{&9+_;P(e795KH!2GCZ+K~i|JCZae3K47IZr=Y_>ku$p7XThG zPLVa-8PK(=wuJj)Rl)(b=O1hu>HcpNO4aV#>pSP5@w7>OT(~P;vYiB|V+<}xH{7Ij zdGcYKTq;!`?3f=l-!K#V;}~3K%>ax>O}#j}wOPP4CmaRtrk+Tr^6C7zZ6HgVw@sm0 zfb$w4hcP24IGi9Nkc}-PDU1VWE&Xh>P_~jkx_ttx58H9W@m_+RCDl~s3U;%qOqGvb9}ju{q58*aQqkpqK^CMjabCy|{rCZFzhCtI z$hYa!`(gcgf7AOL-oNbqXS~1Qz3I()v)*a*i*}X_mz*$9VGj11H3y^F4o!B#k%@_X ztT;Z7$x7~vg_#v#`eATc`%*I(+Gq?P|DbOyJwH*vk}sA_jmN%NxeVZunNGwdjN2E` z*DV48FuPVNHU_i~r>HT>8aVlK<`(vK(VdSgP&@wU>g;qlJHv2<6X94amg?6GXlfOn z1dHzcs@RTELA=+Or94>Djly`LpvUZjsFV!s46J^sl}kBvxcVSYFv03fMllLc8@K^l zrbSZLsL?|Asc@PIN0JztcQ7Bi?i7bLq3pxy_uAvc>B+vF7W4UZ5@4>$L|k_(565Yk zSTnB}4=XULHh8}M%s3=zd^`>p+EHNqU$rp)`xvZD6pQI3>H*_$<9xfZ8*&~ z{=+}_zIIXH)H~y$8~t&OD6C^4cgQm4oG)HBm)d7tiGk6KgM8@mWE92+u(44vNMgt; zM7`R?UI|(&j>DV+HdFP9 zbUMBZfgL zt-FlOPR?VS5M~6(G>Ow2YVTyOj3>h5v1GToRVM80YMzF3GzZ(TsH=Z4R?2O-D>o;t zu)bv_^&nqU86L9 zR6G_bkUh%_)orpgI-fmS^V7irXno@ki?Gmoh z#xm^B>Lpz1ci4FHW>mxp!67>ZE9>Q}=2val4f<%+eC0vO15RxuQp^FnE#(>up2p_W zLqsq2M50$fVuNL`&$Q-nviC*%9nAZ8*uY?CyDwYR-9T&b-k+4NfeJ zn&+{lUiVN>Ng)~VNZ+{LP1hxxH}qj7zqdR9xt z661*!gP+6lM9S%}y2PF=;GE4@$FO%(f|i6%Y4v!JE+=cHiq-CcG{cbxDr;(y*NXRl zL)R8KK`bfgK)~jq^Sfw%-hLBn-Wl@;5dTvrM{ned;Ts!avZ-0f!(4JIVPugx1al4> zXm!k9unjd`s^?)Y3Rm?Ub`Xu(xUm5PZ4?|062ZeIm}mo3qZ54W<7Q*yI_5>_BR;Ct z>u-_QvisEW;`j)6R#qz?JuIOI7``}vaq1lAiP&k*>(0--S!ka^2fc2-{$K|UBdW_O-^obC!Kyu6NHfGCqv$$zc{4+k-DU0i?nsq5AjL|5W|=)PGI=m(?GuEw!!|RCB5gvx@+O?zewX$VFo50**Vdeblpm zK+FFrbVLJI|D9p~TP^=-Q9Pb}unMMU`Yeh!+Mm**INg^IGPfNcFC>zBGJkOS&pR2} zxreQYS2k7+y01V-OIe1mB9yB77EZgdGl+Ak$2)9t=3~w@^nv{jX1I^c^<%iDwl5RI z>wOtE3JE6t zTEJs{w|O5F@K&(BK!>f#LHpOK!~_&`Q${KhO}U4ybhwK3N~KV%mI`Mc#_cpNBr{mN<70Y428#cVdFb+P;CuL|-IQ7JSIvry=RMC8l;-6(GY8^kc-rqo^ zFdwf`q_7hS6B<(AypH`HT)fuTX`wN*GBY(jrOj+2;08`xtE-rZlr`(Xpbis5&Z_;Z2Jdw-rYqZF~l?B*BH|Q({ zak|;2{LgMQ?6niGRmSo*3E@VSjGTc4I&bNa04wjE?8C^5v&XgpWgo_w2400RtF^Na zSBqhweCr5cXFpb~>CM7*-cGTmfAh=p!1>g*bEGqm={8KxTHD`sErVS&Xd^UsIK=!i zrmVBnGLQ9bnZ<&hOyMQ~gw*MeR~F9CT+S>{U0B93!#WuUM(^{bc79<69gxvj0YE2i z$Q=F*>S<&V=JLSwN6mmFd)W2IoNqIuqh6 zS!6QFwoQyZ2V<2^rx1Y^n6bRj#$iPVc4gw@6n(O}6P~2CC~WtVel+w7_&!#)!MnwE z773J(PS>|Ot5V)L>LWTveZ#3~M-=o9Z6r^STAMbk;%(X>8V+q(Dn)T@3EC)n4z$ra z8K$uu+QQgbrmH5jlWoz4D@GP=-%74pFSXByhQcs(Wx%#<=Izl!^+q^3fz4@{Pcz~Z z`jP>?9KKaJha;UDHV?as`2y{fvwi0^?E==V)G$%D55~b>9KM&)dUbcpoeGm~n&P~N z4Wa^?0^6-)FotU7h~*UL*j;#Qlp`?kVM{u^X61-tJQx9A?7ZwXlci;DwYrt;%GvB$ z%(0vUMd~RoT67%TW!-F_!@U*rZN9g{W}^?>TbW3uaMloy;ciEMes+2q@c1*ZJf+Re zUYXINw#m5<=>7qAj{(Q1H8(Zf=pc*GIP3(XE=CFilSjUyR7Dq7sui?tn1OaWt0%gs zkbIaOOy`!y!FwnNcy49dGb9lk=1!MHL=spT<91{+9YycFLkAsnLkt}jHm9*4RNyV$ zdEE7~I%m42ibFlf1BpwMY{$^uGH$0Ajcr)aMK^@1Z#1pfl-?BG-O!e-%R5&(mv@|! z7$7d_shJ#f*)WdakOLo+f?l~p3d@m8O85rT5yr)<4jtUg_zuap6P(sp?P(NZD{5|I zi@|PI6FHdoOJnu~vz8dj=)UOO+00p#5Z2#28qB8CT7b9AAe>El<*>t}B5sCY*h8Vm zwQCT4z8&RQ@4F0PLd&Cl^_j16Y(V4P``BbF17sJMRQZxA)y7h33-3tcr)oPe_>9|T z7?dzatqm&XW*ys+m?Uu9MEW2bn`hXskr+ zegB>P3PSoRE_7h2N2<0+?F<@~Sfth%by6bzNv|T-cJ3tMf(i~*z}@e_9e^5lu2w3r z&J$E9v1q{3_8xR*pqn9-SbtuE3X7lw@Q~=eoTdlq^{{$4DF<8l-yzP1R4L_AdWe#4 z=m=~hu73>G4d^8j;4~iaK*frbTkyXsenBti;ek2`zkJy5?N1O8CE^C8*eD?YL?8Gf zDzNHY(#>-q2-=Yw?J+ojt5Mx)k(QNL6!S6j4a6jUFZ&TD7e6FRYp;zW?nXu+buC*z z4zWBU)NgIj1*oUlE|i&#!R-clf!?tf3N^M1WoE-~L%k|bIoX^LJtE}<+?38sQuHNw z2bJ&~Y!`A;Md;kv@i+)_atfs5LQW_jdO&|JziK&Z`8!bUb4E-YbargHkc4`hZZ#cUUBkbYme^{$=Cm-a6L z0n2)wo@I*NLVE|o81pNk59XFGiEBEmkSf3(&jZH=B1{1$hq&b0(65!}uy)%UK^cchK(KqYJflp2))6y-75!1+kEw*N!;Ln73>R}DtV@Uo7$ z35gJ7?l6Lq2W3#xZ!{Tm8N^^(SvU6IKHLvQ$Y3LcN_!;KN#t;3kYIP{~6T*XzgeaNfe{T?1Fnz7(j0T0Yl z7$Bq<;guFN=mejKNWD{p6X-ydVf+SzMO!csN@ku zp*;K~+fdxaBZdc!OVE7oxY$b%z(_b*@;fwsR^+Cj)Nixrpq4j!Z+`FmzHR#*?QKU( z+<`fE5_MpSp&iKaonI#%Cmvwg1%Hr;XZ2o|wXO#hm5+3NRg6)B!d?ojdZ|LVgwVI4 z*h!Rq6voSi6TnajSPBZtiE|)E@fe{}2yk~`+3Mkzj5P3?OUTFRQ=wSUAB4n3O`U32 zrOuQazx_*En&kfgALY31p&S^&0jiwcaoB?g^}UEi4-QI?7pW`el<76+MT~G|G8=vw z9Q%UACr7ouP(U{0!J-5k3-(ukPjZx!3LtAM1Lv1YkSXK@4m=o~L-wHeMO+q9s68XE zAQvCe-W7quSYFDBYke&Mg-UIpxa@$tqs*GJ%+{ z*o<3wu$MC8X2uElJ4MAoEJPO~*AhM|T|d9%&;(>cFaW3la&gnf>0-eB?dKv|8N{C8Dsr(ieZH0S*(@ z-1Bg+#Z(`qubhvU3i~LL$9)wib&QFp$1oF532@nSBN!pdxb`_IW`lu}f&f<#{C+BD z?+C@=GGvyl=1+++G*XE28zzFe2{Um#ALe)5c`N>d4Y=b+G^-~j3KeK<!sn5k)MuY zb%I5HrNI+8kK)0`1kuF{pg@ZnG{E*sI$7her_`vU?g=-9$|Jr_4@gY+j2)zV2=~sO zu|opw1i*<$G^sNqY%dHu{7W-t@>6xvFZIjxTeW|k@B}YF@5k(4LaFVJxBJzB7fyn- zI--CotTk7&Dd1RM!zZ@mmF0mH{efENHo|L2|y{Mj##ghq$Y`GUX!2n?Sv7kz*e81}vD^QA%n z1{fV49)9Vu*Z-q7{@<@icf&*@O@bwFq(mx@#@9T*gas699?kQ3lL|~kLlabT9oZyT zP}IvU%nNKRi~TurVge0B3rIcQvnatXy!{dj5|35@c89w1r3Tg0Uk=jFv;b`G7_B^wKB|9 z>+Oqh1QbuL$(#Q)Ivu$ehnym|uSu}0RD8F0D5jzS#4~T~zYfnZz?{(GCmIxhZzwy4m;-HyxeI2De8#%X_b!|?~slHYM)_VNQ|rx2otov)jR zn}8b)3o=Z->A|UhX*)MgfIqy|34+ZFJ1~E6ADrbW`ie0_5wT2C#K}Q{nN>Hg>vE?1 z%*DV^ZukQ(X25;N3AjleC>jpO@7To*xFyd?x#_v#IMD;e@8-cDAfMe8#>sP1E=R7Q z@K^T(yIe1SJ@9a8VVcoh+g0a=dw2qFxC4^meqfiIisiD`Xzpt_6u)yHTnuh%%>03O zZd{D@Kwj_23dRvzZaD}`p<5AdqOR+Jq_fve&kg6gxJ_cc_&~wA)#QqT8_jjOU%3vL zbAIm(1__gWdL$v$xrM_C za6zz(Kd@{bAm{+~kKyI?+y@ghFdBy&_?2mP8FZ;X5W{7G%a6Zu+ymj*%YhG2<&wed zyIu$U&VAD_$${@U+T+BvTUft@WQlguXbymRIE+u#ZvTLXA#WL{lyp?Ke}g6s5qg+- z3f?!^`8J#?=7%&8-~F7TD?;rK%||fPqN&4{aW4uVFIEF8rgwSc9!;CC@GI_O8eo#iLbcr5mdYI$%9HR#$ z&R!rBXjdv>rV7%}i-uWdoQ}Sb|<6l}} zcYk-@JK+!d2ZeXirE`?-^qq7L#&g~~;T=EbK|S<1@15U4=?r@B#QW3wecE(6(rCucYX)Ociua4@Tl;Fv(}F;C%*IRq%(*QhfarIC%p6fxcNBrJHJkR z$M2-$H}x- z!>3+4=|A@T5&wxdLdQn@qa*&nk&&Y#L2MeF7!Cc|d?5H%$af5e0nIVrDhvt!>QG?l ziy`0d`BI)g_DraY%A~v?6~!fCe&`E-%>SnUgkSajk?;4q-M+u;``ZUJ1eSbLz6sxH zUu$&#s}OGcoHotM{s!Iqd5`b?Kv((!yqZ)#f&1^e0c4ig6`)PuY65+huWsPJAL)f+ zxQ6~F*4>)EiHk;h1GsEJG68lF#&QJ2y`TCfjui=ph>*h8N}Gh)gSEDE5#vd2{s2I! zS}8(jr*VA)HllG(hE=B!1+VYZ{U<=|7`W)pa4dP+eJlb|^nK`UV*dkoH=!~I z?HT|M=64QN027BPfE5%KXy$sVuVhFIn9I*zI0M6uWxrf3?qi3>Nl zsvbGzXXHz=b!u0@p$7$>Ew1U*OF__2W<|J>!wXaOpx6ZSI$d&)7gd z^NG|%As;iwQ+j@>i55;6a&)(s_s-}_)yjGewF(d-LX*OjoOF}HG=Mmr>UORaeSkVe zWNUj}!!^&`;hO#UVR*L5T*<9Eiq>Mq zY22@Ld2^;7ep_%-njoaYs@hAOJNqJQeU?&J+ABZ8&y|ti?n|0jkA^N7~xq#QgGdn z5(*U3%;|Hw>Vqaav$#vjIItBm_n) zR!unxg`?x)NQ|{bAFQvX#pwmq*Ahks+%j{17F)@EBQ&&V`dVR#E~=|oL&7|O0BIch zzQFb?hYN*Np%B%LC}16+%8AxVmn5MHk%(Z#so*SzJVlH_nxo{8S^)Ab6hCpRO>;PO z`6F?4^MTMdx6T%8xPm=apejY_Kxbg5K8CBydS%R@M!{RuW2{I}Ht@kFgS5F55!?+Y zGRQ+@bfDirMp$ps4QSkIwaX{*F7; zO~nA6Y*I$CKA&4M-`_7l(65^kkQGjzz~lz#MS3`?=TZA=O1ldwP$8MYRDa%{S}U3Ln*A0i^A3yV`1 zG8X)y`Qd&ZGHd#_sgpWobyAgb*hmz0BR7!)oNkobGz(BT5=qCjFQR875$HY4k6rju zyR;2(7eZo^!ZxAug;gsZt*6s1*XfvNw|lMRj40L*U1? zK({bAG^AW3@=qKfKM{#0BZYW+!icAOQl5Bx@~5EGQPpM_v)X4%hhd_RdPaXH%#ZeU zVj^^a2|ZGn0Q}QLzL-z;FcBZf1TMe#Q~|_k;zsz!c4yFkl3M5k7dn7}#r>~{f#?AS z#`8eW20mR3*jzmfBnC3@fDm0V41GhJgu(_c_rFCdDwv4#V0oB2Nj$D#ncv^PPACp9 zLUrTB=!-OZ>oj;n^&VXwplk}o)J5Ea=Yh$>7S`$;%~gQ#5eWENRYQM4GxsY%v%#ng z(9pW2eniU?x=Fr4*9)Osj5Qq8n83{#_P5H?-3@j(u)b4kD*)8qp=BNd>kMhguLhAXHZ|y zn4kax#tN;f6EH^|hmZRGU$uce>Oj@daa-G+XcNyi8bU89FrYdJe$PpqdT=XoVBAsS z1kk~W+i)Ik(uV--7~TKUTA5x)Ri^>>qnBYKWhcy(5iT*%i;8*@tCBQyH0;s84mA?Z zDo^N}K-YxtU{bfow@pgL9a^L@19_-{ppf^^40(m& zAK%0e{O~`(wR-&~L5(&CUJF|Boj8W~KFdaA@kLIRyg& zAHFuqQ)pBW6fnx=>b7N+0Qfw>9K(*l%+lq>IcSm4Cynqt@<8Ow%*|%WElQF1dKJ*3m(MTvC$fH?E?8~AD&zTObEBmNhceq{hB)rB!QgTXb-!d{BHlkOV)#mC zX;C}BxbS&qZc&?`U4m_fjCO8racL&&2tIWHPl;!noc=6NF7_w0J_#(At&%>uXs)+j z1FFP^`7tqkx?dG1#^QKc}B(25_2X z?6^#k?390=fkeNG`rV=WJ@(;?{n(95%4J!K+TJOxvORZPXhS#YL59FAe&0vvUn7*bhLHTfL_D`k(#}Ccy zdh2CWZ_{eNeXEz-ODxvE)TnyTqnnysnuP&|sioQMG90s7<_gL5GpJmfn*RLGf7YMM z`n>TqEODWRw74)kkKQ?xomzZm!x4A|Dg9Y}bk7WUzosk8uk`Dx zkikSOI{t8G=Q9f{5a~r|4@1>`ae8U?{K_*KeQj#`^Lt^TKb7?h09Yi`b{7`Ra_a?` z;l7niePQ|`lMRyQjCL(EjZs%yoW#hxs7+;Nr)H)XpF!ibsp-!!hQq#7qWVm}2{iB8 z%oO;A35JiiEnyx|!Gw>}KOq+8*%`?2((K$dfQe4dEe;@&)bk?7|GDR*TuirR8T-zeLU98UDO=0t~NMqtWvNT5u{6 zeaOhW41O221q{8C2jGLkmks)9!SHQ2Cvu@s-)B<;5i}gQCHFYYryAP)sv(=QB?@SRu{c zg>lylS{2(g0OJ?u(%0>+nLdkRm$sf2@q7!m96tQivKiPlrLH+v2@}cW#2^kY5r>%T zTw1*HM0MT8!Wb|1yIxo;ea^K%PfIHuY3$<3I$m8`F+Xhqv;MpIMs0 zgexu?wAEK?P~_8hR<4-~E#Tp&SIijpU*cVp-cH5E z(&O#`+AWM%GuiCyytbUVIKQ~E{ABZkN3oO`qip+gwCqmhU2^Kn&_crXh2;e^-vSo? zhuc>Bdaz4`8B_Go{oB{o*|~E|vluQi_{F4Mo5wa9b`LLO^vIlFdFs_hg!E^!YqPM6 z$?l!P>n(uge^`A8n=s~*>Qng;%-K2YASnYZq+_UL!(Ul^D{fwuc~J2HQgxB&Y8=tw*jqv%}n+m0eHm{ zOAcUYWodR6o9~O47BA0cFI;=t6A~8;KXlw!M9@yM`iZWnPh?TZG>h&aptsHF2;bZ{|{prP}#q1PKn4b-oL`8olvzG=i znJq(?cfF)%FPTOQAorP7t4_OSD?6P7LCp8iu?*hAxr9Z22FGF`7Nq&p|;sfYR`E?n1|^~r1I&DJS`MpdjD9k6#3Pjw9nJt?6^?OlyU>{eZw#WZvZ z1N_p=QYNb{;5cDvX=eEuosog4{%lXV{ZJ3Fb;n@Ck6LfQ@ZyimBrK}Vy2zC4K$FC& zemFl7iNxZ#0RoGvvlZQfqR?hm!nj(MCGaWS6U;L1S8Q26^QO~JK^&Ry^AY}cY%0E*6f%2azzoqX#Zay&=arOlMtMmI$p4r8Kg<8U{GZGJzWlGte^vhTa$9c7Mfs|HK~Br>$|vQZ z^vBZwBKEDokMfwZUp0p*cN}oxy(g)Ie(#ujv{J+KjRs3D?zZAa_|4s3) ziT}K~FK&x#;x+N2_@Vf|_=-3z{6E4!b~YD+dsn5QSBFIWM=)8zy({EZI^GrXN*(WV zZ{Te2*QH+Xr@h|GAyr?wZrU1^17uuOJ27qE|Ax) zg7f5c%luq#+?n3M)4hSGdcBk6^>oO{^v3;!ye?HA_Xhqhd0iqu>h*qyye`cjlGmmA zgN_$yeZjpnc{wBYrpU`Fvo}dzPKv#WUT>VdoHBo%=#3le4LsiKjgr^RH$q-FsWI|$ z9dXKMd*gpjyO_nqFaZ})oN>J5Cl*ZU@U-F#2=#(ksr>+9t8 zQgt&&8hPDr{(aXKwljL-}OXN}V`iMapTE}~%z1|}ouS8!*$ZH8dd56gx>BJ3@*A?#|dEEvZaKBPq zzw0G=_H_btMqctVRqXYUmsyZ0uUn!~f56SE2z#yaj1M;$L@YkR3jr;vx?=A9n3a7n8UaJ-;<*$1KZS|KkNyGVgI$jg-iecNEW zOkS(MqOa?{fp3tP%ZdiUc8RF^1i@CQp%r`waPF}*kH4Kp*XHrp6;U34x!9Qn9)Fo5 zVCe+gJpPVw(UF(OUzT?M%HuB=EPHwU<@%+z-{$extzRC0t+Jx8pAZXfMm+v9N1POo zzbsemfckO{O!obE|0(bm8ja~@z;_o^78oGA##_; zU+!}_Fps|$85Eeu-_8VMm&ae%%j2)r*HK^|f4MY>qg@_EbPaf@%!3{-Fpwxz@yqC``-n z>pE;Lkm^|j7JfRqG@NMHW(ptv=StOhBAPy1sOHbEH8vixRpMxOvH^)a6n!Ya`hi^% zGt-uF_2*O5bLPd-|tTd@=fVRD94w_=4A(x7j?O|~moOAzxY9|Fl(+K67!DY5fg!9TDd@piNm(g5DvOrl>iJ111)rP3 z>EUv>s-jIvM>n@M+?GiH<&^owApMufL?l;?n<1AcSAK!zIx#r3sJDcNsJ|wSXdGr+b8#53vlLpxS_YT| zuuDvu*kp*itZV0H7gpw=>Y89>-lwYSO3JGQf`AN3DH|D*>5yWn(kzEz?}(IspORAR z?%B2gec;v?t=WeZNMs_JfYHiWu{fTy?b6(ALZ2J7-5{(A(h$37farzl{a-6navu&=`*UKY^TAR`36Hc;2UYRKj?Z zuWqgZnZvMBLzjU5pr*5`1Arhn;M;awsNEjEHYiCHcR$r*vOxuLvnzucCatv_#Bikw zb?F@Q8-^M(Ue}pld}tU&1H#Qloeg}cKP5F}t&J(~RCKj(zf_1$Oytsf47ThirkXkZ zko`~|QNKmMV}5V}pjOO&jM8}lwh08N8Jc6S; zti6-DGM)&JPfR?K9o@CfZjcT1tMw{0{`4&?sRy-0Nnfs_17x~l2^SRGp~E>vD*GKE z0FVOhPwb^TN_1v+_lGe2{H3X+PaK;$HQKDN*2BQ!XsiLsdL0Vex{)7`O~jJ71o>X~-CJ-_==08=Fuf9c$JT zkw~PzTDfs(OV(ZaU%p^|vik#!dRgl1D?kSY4~U-5CTrx}a>Y3_uRIEVv37AR|DVG5aV7>TpOZ zY$pZi1Edtbft2b!=8l|w?S;=5KDSjIX}%3ph5TSCtR1-f;k1OS5y&~>sGVz4fbGeM&U5}os$L44RIB*#({ z6Y2N^inxR5G%xLbA4gHwO&>%keR6cQpre(*T%=BBrRw3dkdG zaR#2m^^b=N(fR4j6fW|Xt2tnqz^b=Jrk(HneCxyATTrWR`OFdu{_VG+Ya50!`fzRn zqbN{r3eoWx2GMG*V(e(=f$so}cWn}boBn}D^|uUA;!Qv<*gYnzOJj<7vk7h)3PQVD zZI%n#1(>MQZ1Y_}3_1rBz?g^3l!2WC{WtB3u~y0hgkx$=udR}N!X#L^xpe6gqDv!07&M00K;r{) zu#$ydZV7b=JPr*vy?QZ}%;nu3nnI886#6tlXLY8~sR;w71<~x%#W)q!L#NQq+Byyx zVZy9lJ>*1sJo2q3(vw{jOrA5}-2EEEReZhga21V?>(OK(3FcCln%jD*amWE{og;sn zA?uCZZO|Dj^`$cneE+0gjKi#E@>BHNz+AHC-PXL_k*r6~?{8AvZ$qWAyG2qGUVU(( z1-KTp;_+C1A|9Itn!t{=uF)oI01%^=klSITs71p0=H(U{e$8%HF)uf$|XKgj3lsZiN*6tYvod3uLBpY z&f4>qRnlCO;DX466d|wB@i-Zh+{RE<)9U&bm5NbBlY|;SV6`SO$O33(TeB2u&lzNW z4`VgDSJKqxxj*LM?m$i5$3f+OYjp!s&@tGggy|gLC57yo5-Bh}9A;85)DbCRn-r+_ zhY8nH3=ddhGl91xfYb$Sv+4Owh90^a_2^w6K6~@G21C~BA zH0Tq>>c%~oHB?2I)!d)LtI!+tAeyX#K)Q|FfWfEpxy?2~yn7@Wdc;=f5vo^(OUx_5 z?qU8ez3_{|&3j1S3)7(!Uo%IdP%|&uK=b>sAw!?^ig}Uj0qqf>xv#+knMZ63DzTgJmfffWGA3xRR_BZkkOz_884egORPuVYfs@xu@wzjsUtI+-}}U_mc`ajW7jg{YRLc5BDSvl^UaKD3KFpQ$dtrD3idZS!gCGcA zSasU{ih_d#!2?bN6*g-C&wrVm)X{JS`^-%^W%CA}ev0U$P+-BhL*?Xw)mHQrl2EyO z6JE03yK(yixMUdi!Oiy;>fIyaFvTP0ZL!*2ha-p=yB09GWvffX3rVc&%mVBKHI02T z5diTj?2|!Jg}WEoj8fVvq;VP!>GnB#vgy;iML2z;(15^p3K9qkyT|FCAG5 z+I~l1VK7Y)=^;I5e;KuZ9qEK=tsW_I-oHz=;`;$`qRMi#5NyPUNo!=P1}O+=7oGTL{y=muzj9vd* zE$T~PD6WQ%1;}3}`Z!dkTE}YGXzUV4Fyw_pjv9Yaxelp4s@$)@kaw|t3f&#qpHjt3 z^Z<2uNH{?tIaFFN(Q}I)G(8z^;vwpIc&L>qZgDqALdI5iRjP629C^(Qp6F+`nxDb}f!h9m*?ZIAxYG5$59qxc8$k|- zmv=OGdN>P*ci2Gh3+K+A+gJ#K#5P#S;fzMSr@K!BO*FbOy^sXQqpJg;L1I2cPL&n8 zQdXp!R20jJVx^oYv8+TY!AixkQ?|IKTjmAO@L0-jH zl`)*tXMOkgd7t;${-yeg!UO}%c!LnHhOA0S5 zltmG2$`G-x4UhyBsW4u%PZ%rej=kD2R@AjkL>%4KuW2<|sh71aA+by)#^u(aoYHqP zMk-t9H0S~txmsx{Y9QU?lqP{DBMT@P@&Onz^=%oK z?oA;ePIq@>SB9cPb*)S>8A?zXXGN=T-Q?8cb~PxGVR9jhaz_z&rk4Z~%K}{DCt==X(df)$_W1)zyU&+~4o&|DXH* zu=k($e!J&F-~<1V?_KYEo)6u>?D}t=|EuEvI5&-rpq$CBVue5m<2qvBX5%pk0}J_; zheY#*#Fh~#qY2QOxkeE2nO*_Syou}x;{^q_T?>vOQaTW@nw*Dn$fk!1`tSm>XuU92 z&DV#OTB**`LNr|+4K^z83Mt_gGB!S}!u!b~6bmQ9i6~YEvFN=VuZdMd`Kan@YbT?>$}7q`q21rgV@ER7eu;T(~Hez9Zgj{o*=kEKAw+6(<95ILMmKBzxp zZ`IZWiNMS@-VmAAFjVv5FtwMc_ZwydM54nHf=VUR(QgQKj3~U0hQO=_0c5AGu&b&P z3uDH{?gfd`{<<+M0gw+yX;10-SUM9c=*f6t5i#h5sCp{0XRR=Sas=^EhH5waA#=tT)Dc88m-{_XS zN~uX@2*}UQdgCgws#o+fv3Sk6^mDkyNt}XUPDc@rAXN*Z#n9DbQIuwj%h1JB^l)-G z98o(5yp=3YWHs$E)=_eO#XKLGHqF$N6qZ;}@Kz4WS*Sj& zl&gY)(>@gi??-DNMq=n=((mR!OeLe4bQF!UC^ql46Q-BZMUIW)Ac&rFC1{#99MVT_ zx^@S9yHZ~ocUUnd-x@6CYxz)Vr5s8Yv{W*aO6y@wo4hea%xkF?v|lW9@x!E9>XV*mdVk1YTv}#fKo{y{ooW@pLb1bf{lfTrN(1f?kk1S8=L;!Gq?jk zG@6<7gNfG%^|iVt7H^mftm&b2GFsFM>1dP%Yk>hMYC+5uAT_ddX0P9739SSHil`Az z8>k}2M59^QFr!Ng?vLFRGQuV4A)OuRy8I{;2~jQ$gZj%(Q4PIe%mdemRU3(`@h;Yb zW_F=!F{BkA)I+Q$D!Y)%jzxv+%plW}o#G>&t>qtI8lPUkbJ?mM#vE)pH|B(LE^Fnv zMdOp*0pYK_#)oL-Uc<0QXl?mHC=t`N1aLNbI+alLW9l{rT&yYr!_##_XjcOo18)c3yV6A<|V^c{^RvtL>+I5GzB0Rs-kEYKxG9#bD~T zRn94`L6qRB+s2P}`=xH@5A%+NNVHm&N8n z2OwZ|n6$i2%JLeVt}et&9Z8lToSMX!D?+8 z@(BzNQ>tCh!wa?48~YmQp8|fuFvd<_vA&Z2zA9VhubIBUF&s$$6wCJJ>$_}mKV%PB zKU(crPRnZ%T~8;&If1PJX{wGsU+s3JGlf47?iW%zxe3vx_iN2{wWb}expMrkRunsI z;WC`u8VW1Q%ogpxf}sgXww-NbW-GQ}R<=hP1UfHS+E5VnQ#8;KOw{l9DA9pkcy zER2FkFO<|!No1aR5IKw~w2@alnEoubSDH3l(w{*^&E>{UQ^eO2fr*zaCJ5uCc5$Wn@IqTU*xaILk zPWXO zGd|%A^)V`I=BpBayImf{KXN5vOZT?O98oD%pEfyRxY&^aMKp;7(TO8SE6gKY#PkoX zQEptePpbB~cj)U|G7cyn@~Vwig>yv5@T%pFt+%*f!sSXDy@@Q_4SH5#Llx8gM5Lom z)%Z@2$k?T;-PKgnzp`qol~ESB4JLq%@pYNDaD^D$M%U}mNK#z+7@-SdlN-NcfZryKD62Xqz&3nNTInytm$# z7ahGNcD@y`X!5Jo`%hQ6=VziaXe11bA@B5~BX7x!?LgC(!Te|PQjLkiw#<&+tqExX zLo^RPG6B$~)^bX<6D>1{@pBZCOwK4yYHAD>-Glu5D3SK5HMys@o$(U_e#}Wia9q zU5nCic*vANF9(@*vP?j?Ga==m-jjQ0 z_A}akQ=YubVZh<8$iBZNl+A^H{h|rjW%|A|q7|$r9RB);5HexSc)9(`QvNwYyT5=y(I(Z$6PsT^K%8mQ{(I5a?3AVlIGGtxln7S2-BG>T&MO z$PpsxaiV}n(d>~?>2ZEb4vaRBlRjq&w4U|z3xUHdD8I5T)7$0m)}@5X8pLBva%w7P zr5(*PX>?O{tIpJV?Gw(;@9kcFdR3k(BJE?HuFI8LcIb`jN~^#%IIImGQe*2&&f!ZQvoBjM zDWy7kY;0{&c1t=QXKyFAp|VEu%Rux)c9<=4kh=I~7MN%1QXTf63V-FNA+1+>9i@V* zyq~JAZprXLPx_eH(k7?c-Cf?60e9gC9E41={K-u0Ig1TNZ+|z(!Tzw^aCB=7fNsyn z9K4(390w(9H)NyR^+OIqW4hhvl=X=`aT(v?+%=$PZC-8&r5}V2nlse#C6C5jMq*5)u*R{W|g>JF!SUH0nRpQsB*O_O$o zNzor~3EkmrS>GMv%;$j-ekuv|8d4)QpaU*5Rlo2s_htZWIsL%T#E0}sJn^{PD*$_IhUz02LJTsdxj*1`qc>@kc1KiFFfQ8Gb!NOn zbjDtX(0j*wazJ6uRPs7xMRCXy0w*Q1vt8+VrlMZomAbgTkV_dLJ{d-0bS3kd0=PYh zfoX+)xiDn0_Bp#BZav_nZyUnsaWPaqE|T`RXsAwmEw)LL$YG}DEqRONFtuvf^`RVD9DRN@Jk+d2@O5H7)G5#%iQ;lFD;!b618E|zMcV!$52ubt0x>q;VM0z5#hYeH(C~{dk z-J5g~OiuUuQ@QMAa={k?%eZ@_pZ;O{+i z-tX_@#u@(a?HLU8zv4fG4!*Z9aPiF9*LnwfzB4%R>MMi2ubeTaUibF|{C$Bf|6riU z816gc|EWNrFL18^!gpTb^Pc{mzMFyX^$+mzV9%?){e4U1^4*dj>j3|m-k!eRR|9>0 zeZD>n3C{QV$uiK_(--P}>)d1ySyr-1;0M7 zd#vkCF<7OybpxiZyMJ?)Q78PPwT!8?jEt;3G9%x5z@%i6gL+_2BnSG*+BmCAW(Nba zySghBhy}l=wPCYF$7Q(9maN4?xGi787^FROz*aHv$s*W)bO-#VD+9*3;Z4!wO(y)5lu z3Mka2Iv5qXDajmu(oWw29qW{2$OARmkNrXlZ9XuT=pIgmD0#%h)guOE9dyD>SRTmC zHcMer5h;%lC+o1E=6=CXfA*&2an>r6`dr#kmDQ|{B5o>I^%N3g6`P@DHvpgaaDfG) zs+wvz)vl@<`-R%?N>zB(CqgKtJyf>pBeO^B+t%-)+NyU{J_o+X@JZz+bL3U2hV`|2 zU98d=LrMr_jT;~DxaDOjfxBNlcev#%*?`OXAs@&K@{0+m`J&WZQhSA8Rc`E6B_aF1 z`bgc9q*R{#o|AXfT`A@OSMn=Q-QE(uW0+*`en+Niz=>i?$>`ivkvZeWXi_Vy2_3)| z4OWe;EQb7^oH<>OG2BzelvKJXk_Mln#Y;YiS~lL5GnP4@qel+T?!qq17t)vR`q#{F zY_uKAYdd3{g^UT|cvxOmO7bdCeKJ-p0Ux#XIaF#tC1)z}&4iq8{j?mJTt1m*)>_2i z@j1RP2P)!osHKPwvIK?uXX@$x<^Gwff_lnuvlcIgg3kdVvz9*f3I^@S(`60ws#aj( zDHw=Tl=`dGDP02uZ!3dCO#BSMobUS5rbZ*iT=C#X<_;g6FeBE^# zz1uD3*D@fy>LVBPt=p&e7OpMGKVL~Pw}dksa5*0!Nu_U0=G;5XnOE%~*hK01)m^Cu zrKmrtaPkUvf-U+PzO;LJbD0z5oJgG2Jtq~cZM5inI6Eg=I`slvCZl$_+LB&z3;XEV zmLv0IRj;g9AMJk1)gUZoaXZVIm$8LBQZ=tMN&ig_fj2k^Ardx~!`3B^yjb56=EUXl zt&&}{vY|cwm}|@e%LU~hGN86249{+_v`4?kohuPUU?2|Nn%a#m-XKnjux%4~TRRqrUC(<2k zD)7G7lz)wrK2j}@u&-LzpD;zB41CMZucE18=+rQ{w<>BR9rRb8Y9ATsyi;o3=X$^-}z(({Bs^v?nqe&Nw~mVg^v%l#vJ_ zt>qD3)|6?iV@vAh*!)C}(oqhdOE&tuA8>w7d|BQTaw?>(b1A0M=ISKhcpS_KkK?WO zJ=t@swaYxHS6tm1GYEn$2U)%x>Me5j2olTTc2_=~5++L-`xIZ_BB{ zK(jJuEP7-gVy};K#z5#SnktR7s!(LBf~vwUN8YrAcAHWZX(hMVIkUe~=Q0mGvdwh6 zGxAJ2My(TS|AQ>0pN;|AdQsn5nNARn z?#g+)*>LMnbImpaXFq1Gt_%d)R~?x&oW8GG(}}KFNn&1$kl(|y6+LQqnNKFJ;<- zB^JL6t^D;MXFa$wH8yWTPEF~pIKXuGz0Sewlf%}}$V(nxS6dx6C3#FPb>-^kX$cwZ zb2x#v|5y|WzpX~OOv*|+qljNAdNmy6An8cWT#jA^X; z1+zeHV&EHUc_CXu@A|y#T%Rhs?DS%#ho)bDTIPYn*@NmUR~1<%e1Z(JKJiI>LKk%V zHzogo#|^`vm7hoseQuY&tk<_>4xI5g35l;(SMfg75z7aPO!t}L{DerKt^wkr$Ipqt%bq1wuF?s0oD^(J6UwRMI| zRElfc(g$b)iJA2EcR3As5nD**9X=8B3O(}(xx?YD=Y!jRHt&Jn9sj_YzVp3r`Tc{& z@Zh^Wec$Tu8SH&^)b9)SyoUY1zo)0?Tm5nWnTu@gKe*mEfE=M`peNq*%3%K+y|;|v zrT2S#-u%wh-oAmeJ^nubD}l3pJ+Hhv*dI9ey)(vl1Ml#A7D2`5 z?|`3oeg7^2q<*o>`zPMpo*%lmU4Prv?flg7SGxaM_eWj7$b`nhwvr=&*S55RWAo@8 z;RYQpFNhhk5E^SO;LFDI3MBKx%Y(&SDYRO$RcUpsYg6eW=HKHGXICOEGh z4i#v;-MZ4#HU3r|h?rwiiRpyiAdU>sxZ17p+mkZ@SZAjXz)O&^vXL~QT!!nqj$_v{ zvE+)?;Z+^AVJL?O586}}xagi4^8$M%Q6`s{7OszgGJ~N$!CuP2Tl*C_Y*v$Kfz2}> zGn~g4R3n^8QrGlUES;c;pg_$8r^d%YY6E$C`~ddVNd=~;l>)|mWnITi1knYi{4ZJX zq1I&@IP}%=<<5npnx4pMkwPv%lAW5GT?Ewd6QbPBk1yD!T4LUFVxcw2O@n|rj|f&r z_=}e<@zvJ5l=#XsN}NiBlettpA5Nyiqw{wc7PC`;KLdRI+~v*JHZW~3V==ib5tp8U zjPv|M^l=uD8@hz-r;dnX`%U}o|7XTbUf2K#L!AZ-`oY24z^Z8-y|MOLX$>qiW zj5tp(IS{V5K)4y7HhPXPXDXG%_TO$lykjE5@U`Hn}jFy%7W~ z5p3G2;0X1&dqS%pARYqxw-RF2BSsYAps2&f%NG2TmcY<_ZoF}P7sONfctnfqc?v%= zK7VU`YW(ii;50aFv!G#NW-6zXGZVqdnX$>+lVeNSsgnl1Nsfov^sEx)YJ;eRb>hm@ zN}-TCHK}9)bH759P^&Lnw_58>>Q*u)j;|X*tP<%|EFUf8;x{4T3&Dk<;QSJ^V2p~* z0H1p!cpdb-V4)eD%8p(IN|3oSLv>H+FA+Sgw*$$Uq`f|TA99a30M>`1qoTGIOqq$M z10H**&?Kg2K7nFPMVb94 zR7>U%lcicNRxvt9m&Ejc*@9kby+J`QKck>&0^`M^T9NKaf114^h}AbHZ;hR}a9P9a zv9?mv#O{0*ZPZJak|2JcF^F_y{P^|^>&bLHn#jQsBxI4j8(df%zXPT=u(e#vKpMXT z6th4MFI){y%`VCOpE;?mj~_y^3~yjou4Ai7d`~#zii{(I!Bu5bRKYKy+7tp&dFhV% zZtHbAX80KlP%)Ozq~o!O7RwcH&1QqQz}AK|%uw$WXNJ`|t5q$us+9;Vg7+BKM{y-K9ee>HP(=+1u*W$r=(|sQ@EZ06?Vdyw+f6CVM!0^WohzIxmnM% zqjJS25OHSY$Ba!(9Aj`|ncgB4h5&FOIKjE|O1cg_ssi6KRtE15$T!`~d#?Ar9rhBG2?~ zgfO21H0>psl4=WI+h>!mNIanxGFmvIYsHaykVshw78h?ouBJyP#&3XmO8+coXU6YJ z-_S4F`Ma_>o_eh1YQzL(*=S%f`w-@FSzkfGLnAq;c&h#5Dh?F%V6?3331A04Kc@0Y-GOIdQ}$HhsW0+Cu10ZLNu0$CdX!% zMyBBWm*!7iR1XZ!LbZugTWGC`OVP_x!9L#)0pIzZF7MB~|HS<**R=C9N3pxfjei;b zzzQD)`F6=fzU{!I#DV^r@{c#7J5x9&8txMA9p~}N#0Q0NiVs4?WI=*K5_LOX9KAgr z62Gxf4AvYcis4+=vP zyj#f>9`MF+ftZ-3^6-Jgk2+q+0=JMoEHywIA*KHEaH%8F0`9U}JSBd;`=yQ$o4_jd z=t>R$qUKugb~-q@hBFN$7q@pj-Ac-PJcwh}EcZJr_Qy*yYKRta7^gu_u>FC;Q4Emmm9|AxZ{ zUb9+T%M(=?2kjcM-5@JZ>b z!S_f)eXqXm3?Y8tQv!bzd7xIW567aZ%yBN-fM3rn;AG7P5Yf6>&Y;Ah*K3D+xw13a z*EMc*n=zd~JQCA68c*bNxk9p-Eb8AJ)7gx5Uk+wfxcds7ZUz;$n?S@drwsC(B9?IF zK?yrLiFKfr@8M%a!x4?bbfKFVJ1)rcvkEeL-I&<90pq`l|6|6@CuHQHg*XyFp8xzc2goP4PpgoI*Z<9U-Cj@G=AI^eC{#2)w^@O zk7|Cfwam`0|N6eh~XX_gPi#HZ&Y;io6Utzo!Zy3`%&{$K@To!xPnz1ouw0Rcq9laLI6(E zq_L=B6oR8YE>XaqAT(ED>~SyN`?U&LfmskNwCluqli(8gq!QqMIvX6Fn1*4-f0yVo z$F>ZBDADJJrzs;Vv++vm!xgiYC2oe<%4VE=w&abFfDmc*c65_+DF>^KPnX?!;?rw( zUWmQBW+Fie21@8is_h(kDp8g6pA1UM*6PkEgK+D$E$0b?Fdr{QqU`olkz{6EV0IXw zm17&SvlH9h@h@zMX%F;#@b~`x;HYwU|GmFKH;4c9yBUVTY@z4t$dF7xh7^KUdsNAX zWl+y$_JyKpLfRyLGTm*A?2JeZpbHP_?bpC9$-`+@%AsfsGtw^*NM2URoRVHQLp@c>!*&#%kHFJ7 znAg$udS*(!!4EMJ%}^utnW?Q;ce1iHFKm6rKC*LZ)*@O;Pi10SE|+Oyq*rOYDTqqS z8dGr<@c6bSGbnqN_HIU2;>qiavvcC(uB#X=tk@OU6cy~MUM)7%>J2!+9pqA@Se(_{ zwG;-kVX+6#Sf*K>zOoV|C|H_Z z2+DYy(+aa~RnBQfS^9ZLS)cF!1pn`cU0#>x757cow)3w!{!#ZIcVF)MVXoIWPmsa4 z1Lp&t&U3$!-N{My&mXFO65W27yi_{kKUVCX5Q0JK(2C{ZI{HOe z+*QIQkzYGK;xk$4NsK#{9-(?vVz7xSv5vq@?GP{a>?F*~^xm(*YY6(=0<0900trx} zfaBVAn7U<5?trJ0Fy1-TeHdqe>lY6vitz(8Hk~=ej8)y2B`hBnKe7)*C}+38X?ig8 z++%Ti=aEzOv7olI=o1QGRFvqj$i3m zudxC;X1$Kb^9YGkX)PB&P@%~4S7;$S2g9i%`tJu@Iz_i+BG26|*LOhUIZ7h5Xaq2x zNIVnIALKfs&tD5RH<;kDK~N`m^xO*!u;Zjz&*+cxPP4b`W8?BYu*jA!3}OS&SV2~f zS~K*ZTE^d?3MWUz$ednG#8AEJw?!3QLj?gA?Ko;?eEPW5*s1FLea)o@FKJ?2m1v7@Fa3?BOhWl%QTYl^vGd-I{3R2IQGkaqS{TV|DO^X4{Bz0XS9 z;x+Ro+ zGx(`k59`5CC+7&@g>nOCrn3hK<|DjHvrJF1{Smtv$VQVl5l~8}0iH-WTj^KTPts+C zekDeoEz9I9NgS~)8@x_X!YVO5iE1Z6gyudBn6(TGCWrZVw52AZ2VxX-0d_0bqP*=L@3VF0ab|-HI!@UIuEh5CbqamtwLWP|}$K zW{j)XWCyE|?i!`v|7{`+n)_M1aaA12^|Hi~lnBiAwwSrCYYV5tnPUn$H>Ki3&P~lB zYpfLJFkIeQM^1Z3MUxJhp~Z7eVPz2vB0bj%$yBZvoj~Q`Xeb>{>!C;@mWs!tnPgErMqzhCEjPP%D!sr8PHcdm zh?O}JF4s}xbN~h?A_+a0$!D}eG?hi`A=*|Yke1M`HF4J{*ipZyQFTD&$I+i%3*Nat zM{r}EkkM~P!(k-OHgq~sfUz-#pcL`tBTzcgF|ohc$Ap)S*vTQ$34e)NB$7-;q7hkC zQKmHRi3d9yM`)Od2;UL@a!zVQG+Py!6ovL7C1s!Qcd-9|(B=JKydlrex&Mya;~H`n z9KY{)zx%_k2fy=nmwzBHei07i3-S26(c698J=^chsBP(@HCsEZHOmNyIs?YI*~+5P zH%43E=VyYr(XS7_X?h8mhWa6TG?BuHJ0FWBJ4}?sJY*U>(5u1Qlk*dk&tq-%O_oVw z4MM{eLM#V>!`>zw_gf!Q4c*X=R3iq0Za$icrZe%} z(#+)8IM$ulC&$M+Y;<9fuTNzsuvEW({VGN-lb_B$he_g!gcrr+3Koo_*Y!tma$rQ( zHCf<>57fDY0@bwQ#mc3KFD7HHNMztz=`n$CPhZ8lk{RZ7SCw$h4J}`@w>t7)c7rwxMTCPw;A}s>Dl>-EEb5jPb#($ zc>G+T<^Y_RAwCQc_zy;T2y2gJz$^3zFKgPh*ve3oabx)Snxu=lTrq>UKr*l2#Awa3 zFU;aDFh7~Ss?2cj&dwhIM>u4Lcal{hmTHz&AygJ}XW}q#fX4c=^%`lVsaM9haD2VO zu~b2ef{PI@BC%A#xD6i}tKt*YZk9#h|yb&tG!*u%*w^BkwF9 zU%7ZJ9m^zuvJc1e(@QrOvm;pQWIsJ|z$-Gk*1X?9VIKnY;-yFUYpp0nd`ozQV~D>V zjisXDTr7+z`gV3<5^K8nNIK>h=H$HmnMpo<%MzVOYFif7?VBG5QwskJX0~PE7SX|+{R*BLIvm&Mv814R~ zEXChwg-;kHsX{T8EJW#oOd&hB7>q}P6Z5l6bKkhuYU_jLT zxFWy2&*@O>D&=49e2}jP^Q1%kzF{+LEoAW?7CIpAGWkO*?seV-1uZ`fvw-N=^}7(P{DzN8HB3CauLW-^u_(6 z|BERmx)wlEfW+48OAE$(Eh%%x@TSDJC=`D<(5|TSLsph;A@Cj?`drerbVW zeiBJPFwS)$*9C;p$g^k^1m4&igE08bO?t4bue9cAyemRc4(_ZGEye-*LFSf-E@JqI zi&7Q`vfJ6`CeaNXk2L(k9%!}Gm&@1sm~y?DKT@s&LP7XIoQpKFx+W4!>}x*Z;GeZ)Hq_Q`LW>j?9%*66B=nf z!88P6Y52Z4UzK&vYlTpe5WCMcwGWQNcUm*F@drltkv5Ja-bvy@uBCF3>Fng_Y;b%A zo?(U^j6~a*og4r3gmu{TqN)#r*p#n^5cXi}&NfAYZ6NJ^eEODrw>3>cF|avO&}2SO zBNhwML_9aKG(-H4po|G|bQ{US_@5*xJ21D29fwU{=sx`~THPGhs`$VJu-2g#w1=k=V%6>VwaX%#jjn#aId(@^ma2F5H}57)OG3eIC9h2rDxoJL`M9>2UAT!P`QxQ=wkKKHe6b0z22OBc65;p>^*PWXU_su8prD^-@1n_$ zOGL@$C<@g}$iz=yhj&|(&lvUTa5NsvCBu3;Ry1SvNV(xTk&gs#;Y9ts#Wth%NKxTF z5#AG5s8Tp}Ns$-~K8}55GK8v|=I}&qt#ednY5KY!q17CLw9; z8D?gK*@>k|;@6zi@r+D7&j6-oK@%kaLgo-5IZMQ@Iei1Z+Y)Eo;}*7jkqsI+YJjOl z?piboM|I*n%q@-H8ppq>!@A)l+2@8umeyDykOu)aq&F}EJ#AOtY+?WZLEd=lNQ0s^ zO^3BqxEPD+Fw_zSM0o4*`Rn7fsbaKoER7_COGCt=A<)jK>@81Xx=rrUM6|02r>)oU zsTHLW7g&HtlA$I+XK-gx79TIbfd`e!G;$2*lSvfw1Q!Fpxe!^L2R!&L1ap{gN4OgQz1`w>0$k8ocDFg+n2*4g*W5f~xH}?fb z*GJU#bK}a9y2gu{OoW=|iA5tEs6-4IN5nFvwsNxU-O3W%fuIgZ>4uQk5z^s=iXK?B zg)fy*A&4%@YHueCA=oq~cvuKiE+8mRzi{{YKF0t5lP)4DUvhuf^)t?&byT`{yFT&H z`$zfjU-SRSzwXzLxr+PW@xSW#`u>^kfA{@8-{1EAw(r+{|CaCPeLv^>!k6X5aMiP>f)V_ia>VF zxSRzS)@z8If}`BReH}9s^w`WNvA$q2P{{OmU@{*nqY56+1CdUH)v5@TZ3liVD+EAy z$SMfG!#Q#_1C(H}W9AC5u;i)$qU$QxP+oFXERvlo3@o`y;DCo#uIjM>vs<|io4(oi z@OEXf5<|Dq?5NoSCay5{KYC3z=c7o!3)*Pb(6-O@c16B2va}b_!t3`#h?irD7}3`f zaV&h|HxT};iEUb`0EDgvngQgrRk+1|fQwcLs)eJqCiA&SW)ZR0 z#${Y1tLtLQ2Tb^sjz?j&f{tO|#^!2pHlJ^<6Lf|!jo9TO%R`SK%|Q$YMh_hRsxr`l z@h3EJ#U2JC2{$uUZV8gXFwu9kjXHveb<+`|Z01Lm#iS=hR}&<{$_=C5c5W&NoXQPE zPL)}xuJSt0Wx;Z(2bFe~Kqsn93uDGlZ-c8nv1+)nv>wL-slLoof!uxNi>9_pTf;PK z7}6Iq(Xcihj1Q&Q!X#3`)wSTAnL85eVNS>wM%Akt0rrt5z`fUKFr4`98t*4JB+07) z7W?<=!`P!%8se!w+^i?V;c$JqoH^05dTC*TC~X3?F5&+x4Q!s;1zy4qsZ-K*V;j8e z$6Z%YJ`X|5=j%eo0AUYl$wCY?*+eE5jkSXU zOoL@!RR)RU$l^?}d(}ta1@H47+TH?eZo$W(N=39>@~>~9)^Uq zvyu&|Wxz%~wqL>a4geu>fg zrHaw|mRQN*PN@u9LwYWf!Za>g3}<4tff+1!FK0$5Tl#Q!7-YSq=WB?6TuaGFsK6A zrgJt>cs(CU#v-YqLN!0M(pdWjd$}Vun1gq&cN8ppee*lp0*bx)=HY;~^?E3UZEA+C z4qgIB8)HoTnOWa(Q^GjDUYFo4V%Z6wDATy3ZczKM)GZvpf`MRg9w2FRfzy%rS`8ZozDLQ_{aIqwDW7G7h;CopA0Xu_CY z*`Sq>Sr8J2>!nIrdk7X40|c7C22=oKa8Z{=h072J4>94kND;=~GSF`T2FKX1+e3z8 zG0PM|RO^6hB6gQV@?)JF#*<%_GK2}3l#)ocVka+_-t|zENRnn5Ss*E+u$3Eps|pxu zwo4~#gju>H908GX+GY^4nL9{2HwU%>?2Z{%j4uwgBd&&eioq7mKcgLQR>d7I3!$Lm zBkZJ#W(xv0UkHw2*e1p%7Pqya6?JIRe6!qMFkY-##KRvtr7{(5v0kJ}B*zf48kM8P zY1LJZ5{1(WVAH`QeM6I+*#^ve)Og=mqevs$TFnu=Lhp;zLyxEFj1 zR|y|H^QqC;_6xwd+js|K`NPXnIuh5|+#x(lw3nqj()rgH#Xvbv)YrocQi5iTi2K&k zdO_w?^z+ZZZ%>$ST$_mRyBsPu*0D=9(>|~&sic2WtJ3vtpO6{nru)G3Ae@q3Ai#Ju zpH4hudd%zhAr1B5Vy(Hh-s#T4N`xK@(##skM3&lTQD1Ceq%8wumNiZG9urVyW)Zfb z;tGVB0dq~38Ts7S2SG2C!{Q*xNpYghA69 z1uqF40Eq6Q#!g)?Jw_vD*IvlUVWu{3?VU-&GH5B#`6{ZqB*AP`NgU*9O;3Pt;%ZI& zze`IYf4cws{lopi{=t4n-#_mAhkbvy@4xK(Pk;ILUl82Ci{So+yW9hr{;vg; zq_3NUTj5YR00sg7m}{pij2E~dir=05sg2Z*%m2n}cIY4g$d; zhH}|LvUhzJ9RlKs2bmUoH~KF*pbwF1OTE(Fh87z9DNR) zC|n>WfQF|qCOj@mZ$aY)<&0*vkm}T{>YmT>pxP4j4d?a^X+T{>{)$(mu<~E4#_0p0td~a~Y0iKQtpKQOg|A7wd(i89tQ4}K%SojN zoNg6rd3%Bjf#Q+TQhl7SN)BLfH{i2ngnHE|@k+VP%w3MsV;Mv~V_ZF!GW%p$@X^Nd za_OlIOQ(}2U2T@PM!2A{>QALKypcyp(E5UNHMD6J?9Z#4Kaz)TN24l$rQoc3h#js2 ziTj8vz?(!m_w~o-lLsPx*Ps57D~AJs+b2u%jyXn0<)({+SH?OcTTpSet!wgzv%4W} z>Dn2V=LW+9;2?R;Ctc^4131Y!sL3jKolepM=~51t`x>g^QJI5Q=uyv5tE@+)7t`Q1-Z6;I`=GEiTsGq-%NQdjxyr>?5L zf4P6AUfwUy#dZQNH|U_ci8bhQxUjI*qzgfv)oTK`V-h8o0g@Co@Br9^nDps=xpFujR-UeL z2Cc-HdRGRO!{L6k!G`2XKNn{m9+Y7{SFZ~!s?7-3Kv`|n zv{scZa0n-9|YrUy$eL^h- ze9!5icv2IWA*+pt@yv*j(_XiWR5y0tz~j!vn@j}td(HaowtfZKNS*_weZSP$8sk&9 zi{%hc(H2A0!oX#${~105I=jB2h&&L1t6Lg%^zJNk>~nh=@;Ub5tqoOi+F9RuD9^WK zgoDZ~yYQAwF%UHyPo-tuGF;qlAHH+z$SmvI({jBncbS;%@9Tz4O!rf1OE1jB?yNj= zx+J!PO5Ek@uD1rbX+mF?S&7}Atrhvm=_HQ(*YbhO?I6oI$Ock*iWwG>EZR-@2|oa6Z(_ zTN9kZCT*z52F9XdH>migq~7cDswpv7Ou={)RC^-emkmV&-42*1DT~|fK_5Y&XvMwyTzp-_ zf2?e-f&GhdbOU9!q}3LJWb1i9%B6V%dY zNNe`08otMw0C0Do5lY5dTrSr-~L+qb_L>>+;aqp{MFI z#!u(V`>&{P)l+pww^=NUx>SclFCV(xfA1%AcKYO1=~*a`6nww*DpA!C>g<_$Fz1fv z^B7~D$*cGFUp|!iev9wt_RIwKTW!Bo>Sa|em6Uo#UGAs1|Jk9l{Z#hP4!xo-50zQH zykDcvFM?MC=f2h3H|QS>eDv*^LH~upo_BhCdjkD^ubw>@ICHk=wQu+K`3HLg{k{Ef z^u4_~-PaTEeXBpv)7RhMH~4CQZ?8W9TwmW$4Za)b@n7iez2NWb3-t8AHr#8>^$ZLQ z_V&Me*5CW>o-=1&A&qnXp1?qV4;X>|fyuQJ3d$x+|_3XWB8*z1sDN{r&~D-}ep}pKf38J$&62S~Z3deq=8X7OMBr zeB=_DbRn&$it!PI7bq-534~}-2|cRBX;QLyglKDoxRj{3Ms*u&qDkY*M(q6Yu@~Zm z??slsCtQQd@qp2h;A|!N!06OT-gZ1?iT2jJHFR$RKz0wFi(8`E*$w&5D4@JO( z{urGrI(z{~MF4|fx>M9*YmAEM4Tpt47p0px7jLwKgQ#E&vBWXTqkWyO2)crECx==v zKH0`BY1(jaB&f3JzC$Y=n&OZ~l<6qZwhQ?j#_M|g4}R`1PEc$DCQKw8A>CZ$`@j(u*6?Ycj)mY5UCQnQd@dcltEP1ZfmKq>i2pOZJ-G5mxFm? z8k9wa*{GJwFVvN3JNcK0o3VLz`v-kpA#@QMQd4UlV84LgE{%J2JaHZT0#U1O2(u7G z=c!?-fO8Al&egjFlO@oaaQCA2REqlG1UBN3 z3la`a6COoEq)1;|&zb2;N-P_k%0`(mlfr}LlrH#L4b!aSSg#k#s(Ea5E@F0(EowS5 z+YqLZWQ#nwou&N@^F5STDmwyE?q_$PbxaZKY1(Ig`}?%d=6R#O-#!HHNf5g+k_pG6 zL^IcrJ~Wl?$@HE;GY=z!o>5T60#Ag z@ATZ`qNuyymDar#gSw_4{HdIx~zFcKD zecQylnKbf>t$FR32w}O5;(gP(WHNP!WyaKb3YVq~FRo#@q7|UcMB*VnvaBP*u<}@0 z0A39i8AtSMJ-8~}tTcmnpus^wRB78V27xnTa|<2;!6ubj-fpea@OS9MUnE|bY1z1x zHOkxRzOIjq6lV2UUzjoPB-ouqstXl!g>)hf8Pjw6XEWnV#L_1KD-o1Frv;c7%C<`E zc`(PuqHh8k`cT`rb}$NF5L=nO-&`i78La$hwLq-WdU5Z!6^6ZC|DBX`czEB0bVP2|x# z*9@ZnKhyQsy9O5eKk0kWd#)!Gc+Y>?H|m`P55VtAJ3n;Hc5iq6^}vXY1>pau{y+5p z_x}Id|2O>qf&Z5dcnExhPk?XCm+-yoyWsPA|8MUfdH=rm?|A=n?|E6NlGVAoSqZMBB`ld!5W*`5qRTgRs}za zBJ}`_HlzLjQI(U;zfZ2p{hd$yx*~?xm|$Dnc4J6l{HaA_(PX5UyFCN-F99rYyY#qJ zSy9n;#iN1M9XK>pX2egf?fn&Y{CKOeA0d7=5vHLP_y8PWqL1}ucu)x~lR7aSRpQv# zDX#_+=awW6>xlWLl{O&!=6fc6X#zPQt~`sXSw?9n+F4f7nP`GW&jDZlsYg;Eu3P--GMc_>m@pe3R6(1`U7eW--4C7;{)8CklagIbA_V}U3POvS7 z6S98T9uz|wJ9%Io6iqj&K|Ds{AvBj(M|-(Y$Yj_HB{i*3Z1?hK!Uf}(60D1j(pvrVV0L8Wgl>w}w!kJ<*8c7t3kwqcZ;zod6s)FVZ_Dae0O@M`* zj6UIgOha!3AdpptxU84-A>oQ2n9~HK`Vo;*t!od13&>Mf5MqlIS?L3U4~g+B@3XjK z+GDSu$IT5^4l7EbDvmAB7auw}o&DmN9=@tLmSak1aZsUPA#N5&rkF5HsyIqlK$NK3 zsw@y@aZW#*jGx(=WgzLsYexrCG?fRkIzxQ@#Qs3KF*km~Fp8gQ>Z|~__{>3c44m+b zO_hf`Gct&JjPYj;q5@G9!v)5WV5iZz;um1MZFahTvJ0S7F`7Zo3$g;eSZj*QpzTQ0 z!6F|wAWrfKZ6_V-NE#NiBk33D+$%fNJzbL@G%vq?{7R9_C7=|9i_GO?$^()aAtp>L z7NOvHxpaTu-{`msSrPxN0IH!7u_fe_g9Wvt*MAdTm;JxX`CoPQe&GK%Jio|Ei5t)U zYvrC+U&&s+m`HqKR5RxXyirDM*Z(knV#!3rP02{+ZwFCCW#q#l8e#kwP^ZUEcR*p zUTQI%wC<^J9&@wAmtjZ=EM{K67M#cu9F@2(5)Eu2IF=0(X!kb9?9Af9*xh!%L!1oX zs6Hg>yPEC8W=i#8QVrSXx3L!pb=-K1@+5{cQvTz^N{r0^?$y#ioc)!L$A0(bx6l13 z{rjU|UV^&dX@9R&xODB3ox3!~rK^`T=niJ)jg5OE$mIDkb*uB9(v#FScwvNq#ijE8 zt$UcQ%ZDTL+^gx!%oRyS+T7ks9>}M$u`aJGwo>Pb0Gi)x*2>(oi7t+ICWkCdq`FQ{ zc$a|H>f?@t71$BqcHC-v$N@JmUUS&H<;gNUl#YJ&)V7)10MyEMOPbOwvRZ2HS(U_JN< z^3p?W=Y}d;5OV>WT^gcMcN#Ld*hC1F8hK^6fl7$t&q4Ax(mpSqtJ5^J;ooBUM z#-ilX=T|AI_0_d6FEv19kZkCj&%gR==UbZ_<^<7HFiV*rp<^dVIuVUz?8cX&!USpE zdiv2TAIbD88CRgVGBLe_Tjz~0E@V4<#Qx+E7;$r0$Zot$8FkeqFturHsOT=>DgT;*+<^&?#dY*BPQ%{k>Mn+YAd0ErRC?pw$s>=W?l2Nm3%~IH{=I)S{Eu5g{;UoEH=llZ zZuAP&d|bDznSTUbWgEw*T(dh{K^ziNA!fHuG#2;YuQZ9-F zE{i=GHa_iPZ7pWPkPb;^%KFS+;sB(IL}Sm^fGjQiVDybI{?__G{jJ|!xc>eH*Po0Y z9;OG&e}Ix&ywA*RHj5(FT2p5z2XF0jJ_jt(_Mh1Fdg%bYo{=quUBv^L*<{-kADjO7 z_wZ~MxKLg^h99!q;6Tgp>YpAd|0YU~#~Jybh842tidEelVKormS4gCjT`^Zq*edCX zOJ9BUB>VJxuYT|*gVeaVDTtcz99v%)Uu@mU)k~pO*$WVpA)3p<6erR-j6~YEkBrYq z(Dzud$YL(oa@l!&^6J6N$Xd`ne?+$4AL-KaHJ#ZI#_ zd~1GkadIJ~aY^D9XmtDn3zGJBnYgo5hz9HRYp1 zoU!pAO#b@6QyKb?{^k$9{g1BxRz388b^nutEY5zz(q%^&oRNjepjlL&?oSxY&|&|c zJypiWx%V8bjo5zh<}p*^P!sdgPhc`!Dr-4iHX`T=n7$${pk}0fXnS(BdnXq$HfXmu zez--1pu@-#I(osnd#}QNN%g~}XY55%-!%I~J3y&UGyS9`@7YExe0$tJBz<__Awd^x z+7n`zC>Ce3(=j(AY8dSc9G|fT`RXg#{|CEvx(0qc5b6Jq`(u5--}i&wKkEJSy|4BB zt)A(?Zv@8u|DFFjvHb?UKkxb9Ja^nbc3*J)s_T2sA3HyA{9VUP_aArvsQX(a@KS$9 z|K7Pk*W~EO7Y8q2ydqn|YEyzVn)^@`6r$x5ogpgB+xAmiQoV1O{9v8fz*_KxH|(HR z2NnP`7n?qi2vLCwduIb(!&fqI44yw9$uUEjyp|15s8kqPSRihweZzcQU^sT(Z9kqI z%VPN>eQakTAFzH7q4wSz40J`_|LAqH`DkrJUP6pgCLA5=&9#l`4KZ9n1Zv)~U)Ts9 zdSJgWefMxyG8N6whQNU1^wYgFfv&e+AC?@mh-}&MkY{6MkyFXczJ+<7c|(3>gS2?# zxU}upNqwlXVmS8(0$m@bCf*u6fAPar_U}NnsZBTbi&kf@)^5rD;EZ+O>c-W|y2hdr zJocd}5LSi$O(-F@xR^@({*bmT(a zeiYolVcwqpbZ7wEe3R^+w8H!f!G=Zk`sLvw1O`)fBxuLp0M zSL(r9u;Y&P;O6uw9DNQcbLD7l_(~Y8q5Esbg}vTD*TjbtF|zpp`@srYbyW6c>@AU+_LYGqv zrHdb|7iw#rLw9a$e!4wy&4+~L>b!Yy&>n3A`AFrowo%y&$TZ2wu*$4g)+#l3|>xUi*Psu z!w6ME`XelVAC!n-i=8xeN9$3(Za&@nYZVE;XFm>N-(JR>9oI?pfcbK$vP=M;6JAyC zk4~AB&e{hY@SvV9( z?fdFwbt%PW$Q<*|u_aW~ptDG%q*_MG^Y)%6&^4aD^E&1EST#LBMimuTL`akA%RqG6 zjX6nX@7IMs2?~U`T38R&SCHj(#_=;>vR|INd$9SA7EbQq8f4{Sj=PN??YRS8iO9rj zLb>c>=6IE!CNgWT+Rk~zzG)XLSKTjG`=NC*GW&d`8Ol|SZ|%7PU85f@NfEMk5$s}y zP(Cu`YW%iK(r&16^O;>B-IAysXiV!J`)Bky%OzA-&l~6WoRsbVWADvkiGMQkq;Q~R@ zFSFeQ2qq6n2J@1e_S{S|2=XupFb^~HGDx2Ckhi=92=e*<&N)0}nX=X0?o8i-1?pe_ z?fm!U_y4U|K0vYH0d13Rc(FO%jK179(vZ(v`Qjhh;lQ%e@b7EcZVs}oLM1R7WV-s5 zdmr0Q(n+Rm=Jd^|oBzTo4ZZZ;*LCAelLiSAv`r!f18x(fJWBDXG**tAN&&>^`kQm4 zsYM4R##vsz_BHL%WibPb{M^sJ$m!s^0uK`#k9NZ~-WhMUFtM}754Bhflo7@3$zVgG z%t=z5;obM{by}sLf(=;sVo1Q!OR95H@o*`Pw{O#ZF)XP{BF3&;#BOpt2U$X#eErpf z>PtR4-Hy5^e)Fr+(A4;Q9L&@2*hvCsgHRXfWYo!gMVxVI6i4%57Pyc1XSm1dd=LU) z@8L37?rFfQwcq@b-FxPxCp7l$@FtqMjC35%36(N_C%k_7eN^YhE6d_6(;Wno1{3yX z`t($J$Po)W-%X<^Zzx`o9z-V#g~2gl;T8zR8Jh4aQ+ z2LW_(UiD_>H$T@%f0q(ZyrjD$p}f%{p$+j}1oehOfW=HIUn_ z)9v|Be)DGro?16lsdXf-OkGK%tQtiO6tC?2rm1b1DoVcon>(eUlMg+2T!62YYAS(M z1~2<0Vk`+JoVf=LP?A$41mUZj`^}nm{?+5m`R<9mdtAcKKrK=GeGS^a#jo;v#7v?7UAAb$i?j&!@nqh!Q36bY zdt!FwSnjoa_~djw()-^Z>JL@^b@8u)zvKSLc>i$!HXrN0b>#AMU<|K!FDE+it| zU=2Q)72w)OKX~__|MGwT*UNAG;M2KA|AQa?!~HnDwD#Yb72w(`0Kcfy3Cb@;?_K+d zxLx$#)o)n=Kq>ywumUhSVg;!5j~}@tV*Ur+sbrr#a{w#Ag)?WTr_b$ODSATQ539^q zZ3t{2U3>dSV=rHRYrnPKw4UF2Kg7*FcssoL&JQO4=YR1}|C7J<_x|#F>#6y7j!k{T z+abZae0e{-`Odfd0np-)lQo9P(SG<&|5$uOGzWnys>lp6+lndj^H+)%KRND{U9j|}*gNf(gxbe^a<$wK`AOHH7FMj8L z$bG}R<8^7f7UKEK`{VTwzug~ywEKg}(f&BmKN|0k<=y@9*a7#&`7`G+b2s^o?+=Wq zy?^=Tw=ukW{r#)&Vr>%>b=R-FcYU7~ue8?R`T9s&fA9`@|JA>I?D2Qs|EvFV@-MIb zAOGuTFTeVKf5SUOSfMX(j`#P`O0RwkO#LwdQ%sIF$AkSN@#ctjH^)6LkMolk&Zf)s z8@oK%92md+Vkcoa#(3iw-FLs~t3xe6cw=yNoc@na|BL_TKl_(|`SE}L-~GRZ|LXtw zhBwBySI2Kf>;I#9YQ$HE-v7BF>Hojiv;Ws0|GD)4pE7-bL&N_?Wnwk6&a{pa)?C>w z3WEVYtFyNG91&h`0T*SD^)kOf7qzds${8HL_hZ~rcTvi7i|6or-K&b13e_UY$aBFY z&L|pjS5O9<%fF1{n3nZQPr9dlQ(_x5@Rp?Ow;;z23eqJlc{~?O-9VJSh?m{7Hi2sW(#J6 z_0_596HbaBmd`R<@u>67J2u7#74U7`!7KRRf^o5Z8n5AG^?!AzY#+oQ?cFW*(VkVE zq}e8t5e024J1YiugRSUn3l(?Qrxl1|=49Y4!Ai3N?69#cR%o{Tvu$c^v@fzcEML|F zZP?u!vO^+^GoKYS5SLYG2^P%aY)55v**?!|HJ`Ts0H6ue5$jJ8s%$>5kBXR|S(j4qnp;N7 z9qpLL|F|Qa<>;^PNJ6N-v#bzyUzQ9m7{T5T8t2d+E-1wDeF!%MJ|<9hayPrO|57lG z<;4&17W;>BJvx;un+Xfg^$_@q1kL1sisN^m#x0p;AB}#_c^0SmjC}N%C9~^rt>g|d zwMm@$o>0(CfH=};k2ZKdR+k*9dH2*=?+#A&J;f=ZdPP3=JQjLzj$0)f4&9kK9VEGe zigNO~`pzPrqiR7VpKHtHMeTE(qGF2r5E~pg);qTE2W|CoV-_l~!Vyxp#d_jvi>pJ5?Oj2svq_osDY@b;HTn_~&jkXx< z16ecE;j+AGr4~rD5B?6;I+(s2-feUm!`x=ANGnc_Riv4|{f#H)+j01}XB@o4$6q*e zbadoUakyIin=g$NM~{>a*GjeO6WwQOi{(eF)k^8{Vi{$SdjFpu8anO&2k!sn{4co= zhOX?#1SIeOoZkPxe$#9LK8XK;q5SX^k7(Jx+H2N;Xgkakc1o93oxcp6tuG zH`Jro*Cf~y0o%0I0_KvRNJOIJG%2~rHdb!opx&bLF z@ATf5dkKhA=D4=F;b^SvOwGe;-3!T&9i4W&6>i3U7YzV!Db{n*Y}@~yynYcGty@d2 zTkXY7p=XLtZodCRJDPI~>y%e;>T=u)#w(GFK#e;#mdv^th!pk41#$ycvZl3g~e(IA+|;T^B+}wgUN3z)b;D zU9By!EdU7x1TMsl+ujz;7dTj6nvJ#vcwl=Ct>_)a_Wl$%kKM|pP*|$K%`dgE5q-P4 zLw{5t^2J%o}9heCEw%-eTtUGw-9B_gLn2WmjtZXABZn zzM5SDlEp1S$XK0YChltZeHj%B3@WuXQP~vuI1Dgp)-Z=Xzav#zUBTJR>>X^2YN`uv zZgyu*al#9hTn{DA?Ymk(54d^M`mKdGBYSF;v5j?CzJ+bMxu zZCe@^&rnnV=X>#E0B#B9k%gWlEXhZ$lw|-g%PjAFAm>Rrt{i%jpe^(AStV99aBtpu zRF1U+gH5y1C{VvUB8Pl?oi`QaF%r1EO|ZX3S6rGJxSTVA+hw8iLX%_P(N@co1U&_* zJqcPq+QwM0#jzb0e`&cY6zp8FwB7szP04~(V~;N@mmNoGTHPQb|^E=CgcOQ|#235`7?>olJuZh9T*Nm19-f&}TDY`E}kZzXh_sS}rR?9f;@E zQnSG_pEW2e(z5X854=CqXW!rb)-toOlZpmP$%?XO1WqGd*O&>{9yscNR&(G?%2Dxg zP?ZZOAEcA7<({OeNXLx8=_wuPjs2xh)mo?beMX>$M+@jdeyt`em1EjcG)9NhltOOF z3=w)o3<2((WD$;X4X?BLa#Xao-J(!mZIrdQz}MdJ)ldx9-NSiI2^wqP_wDAqdx64= zc_(V9c#p63Elwe5qBd(b><$rf^B#Kg8$H^aE0x@()=Cqf=Lc92?sOX49}_Bj`K47T zDV_HA3kqVkvbEH!<1Ki39@LV8>dz7^n(^S$`g`(Y5^nuzJnlK1eD_n_0-ed_?d2~Sj-&`oRt_}@UYjrr6D_tF;x`Ag-bp4HCX>S zuG15?A}_PeNQ|51>arW$LjP%NdHW5L%C2`CrFYvJ#LAO6Bg|`k=cr zwtHGZ!M2uA-YZ}wrrvBUhTGQ&7d;;-siY5H@i+ZPxuUOFJZ(YRe7M)wsUG7EJjBdmA%XkU4?`l1i zStU#1`-<|s8{w_k?z4vF7Sd$fGUJVTPY;c0Ydfj}h$QN&oftAlEqr9)0ys4W@g}hG zGo)0OaEiXuZgihlMlUbbU?52i|LASA_BBcEStqYYoLsq@O{$zxjkCX@ zfiJUHVkF;jZO}4=PUPe}ogJ=lYQXk!CoW@PIoJYtUX#?2Aw7S-{NJ}oJeg$b^ z#dPZSwlH$6fS3){Op=y7XC~UzS%VdF#1I$oQ4a`P=3_@i49lFk8iwK4`s!>)tu5|o z(-qkHxzZV&VWyzDc?VyWFf(Q4cXLk6c;-a_=?jwtP0}H`f3G0u+uh! zz=0i3`UZ#sC-4?AveZ*?>=vC(g*g;i>J?>&b=mWz0%Y@ZEwY}9tQ4GOv#?pF{p)WL zGZMI*7+uZ3%dBJPVoMbi^zP!S;puYXM6vpKrBW)77Hdb29yxxhTpFp2l!l2JE*Fc% z-h<`gk_rylE`*5*T{6Y0_4GVt5<%gcdl;1Mn6wBpO@xf|sv_$gA zaP82Mk;CQT>hL4wmui)AtyV0RF%?*<)GEcw;nLB{RIPHNSgMsuwc#8gK(Sn@ z7Pf|pL;qwb|Bo5K_x#ZN_uc=|`A>8I)6hSu{cp9us{OaMzgPS7+D`3GZL!u}?j97k zQW<(_t@{#e%HMr>beDT(jq|N_`vocJJ9Bnw>cTGX{f{hRS25qK*RG;p{Qb)x@_Q9= zhHIDKy!O#wI78A5%~E za_vw7vXB(FCP|<(srH65$c0%A$dpbiMoD)&w>LX1m2pM-QX5!0Z>uavARs z$;O?%gju>vQD4S|o@=XX$Qva9~bB;V`Evsh=*kqv9b>9BqC^Oqt{%#O6? zy!gp$Pgx|~~d~X=# zGW+LrX8PQ@iD|f=ro!+YDYurM-H%t7xbngoumw67Wo74`7Lu2!^LmX#eXjL6I>lGf z>vdUc)8_m#bO$7WR@Thi3{um~sm`|hnd#-E-tk-e>qS$<_;OsYY1yYOeb+n>~Zu{N0yYFs| zt0QLyI&$g4;$Y~!AR2Z9{F|q9^ zEMt9@ZsWMnSn27P^vzxQ8a3hFGh5GF_KUy3(gz4Q6jg-LTw`(U>B&jV$6_^2hvGA7|8x+k)YE|GNaU^FIz6{? z20aMvGm_kV?OMFTFMoWMWAwtsGhbeJuU#_{&)2S@odK!O*RFNHzxAw^+|j`{Pt>Q+ zpN}p?mnLSuuFaU4#h?dAI^YGi16NR32u5A>iOO`VORi)X_q zy!c!7AiD{F|1M0QyPqy#WN=Mg7#`@txv8nC=u&k4!tB(g->M6j>#dpSo0x(7YJT^P zt*6xdX9k)-F?$Ky$kTJ@v5u$PY0qkp7yDIo9d#O*NNX=5#cq~Gqxs(H zboa$Yj-R6j1fo+Yx;2h9EG)I1pFUfkyKv>>S9M67AHQ(%!sOHoW6g`$DO_gv>OQ!V z*epN+;wx(?9u#F_X>I%+1gPf$6J?VQz0yeaqXD?R58zl!PpIat`f1d?btEr*Mn~M4 z7!Q1Af5l%une2kUJP6mF-+ElL;SS6OiXSgtoSvDUK7Vc(0J_(S`tds$S&qg&44ZdW zzk#{9aN)k@;^Nk0YIt#=;ggf$*>Lv4`SX(#6JNKZvt@Mojw~a81Ebpr8Bd$9?nvKbr9WcY+C+?N=7JZ-CJ#gSTxo7dM4TEc>AOjEY+m zUUx&t8mEQh3*}SjLA%O%fhR3~JAbM)VPIlhjj(7L>PBQ15krJylMh62jHEGcwt^+d zF`qeLvB?J-W=oh#uQ!SdPD(6Xd6zU;%65I=O!Fd6f%B9D$p8}Vt^>j-FY?8g9ATqf zaEpm!S!ie81vQsWq)CSdLF^pHzFN?D>vX3%fR&ExT`La}|C>aSGtfzK^S>|tjUs@~wRttiKwL#3t>*PyzGO40=r-fRA*wEcH#u_2=?FcbhAFR*u!LVDWon2XVHbB;1 z8;OzKinH;u%;GDD3+TY(&@yECZI;Zj!GQdbbt5UjDzrvhzN|UfxMoM5?=>JdoMH@0 zfv6afe7>{V?u!aD3hgg<$n(~?FO6y2bMr80%z^4$7dZ>U(bD=)@eG5IUukbMv~X7B zZf^e^k9P?N3J}(zHsqlaE(TRIVrk!nQYkv=%5r}O%7gcooU_Cknc6d|#zTx{;6WuxSh61{+1M|% zegconFz{F)FmF%EeURh_15XSpDiaAjmI1Ch?uq{4u^C0gxfR`Rwdz~15OOUKch?F+ zeo=jMK{s3qEB-5ImZY|Qc$0nI zj%aB97F3#;{Omw4Yp;tO=I3F=YWKv?Q=>&7|LcqRtDYx|?CY=MFZ5Jx0cs=kqMzW_ zdO->y<%Tfr6L6JS*ZbUuWPmnaL7R}UH<|8;eK5iY(o8Fu5FM~-YAFN zUy)LEy;ZF!W(+!!Q(x3O&?-hPW39H$qN0Z1G`9)ksa9OUbo|kp5)rhI_t5Qe!)j6jraA6P!7=)XN z-wMCi`BmnZlXy25ZHT%k;Ech@&&^@CfLYV5RNZ2u6Vn6Mx(*RVky*9I3!AotTyGiT z@7*C{N*cnd>o%KfMx=*54}^fx?R?0FtrZ)eLqPzpk%iO^Ra`l@*43!^ULFF3fwsd0 z^JQlJ7kDaH<-q50SG5;xvHGmTPS?nfI*JOt%W^j~f)y>bn$~ealTnG+jJ$bhh@9KG zpsNXWH&q<;*%j(EDVT!mugpgXtv;#DFe9vWH2|E(ZLM;k!<(Uu@NM5x2pV(aPPnBm zJRq4E_VJ3HG$wl^f(e+>9WC>`pKl071&_oe!DFtEamm>Z)w?b&ab30M)-% zE|n_q5R^*CYY&&NojL-wf3yP6K;@Z-O6AJKrP1LBAnZR_sScOQwL`iaTd5RO5%8tX)}3(W@l9A!zggB{WCb6Z2@q1WfZ zmxWS%t@&>t}LLm$F3)A3Zi`j04%*QcDXrrD*Aju zdMmLQk=p7WJH<>iTb;46ZHOqbL@Y#0H=iGyS?w6Hy!H7Sl6jdSKuB?MD~u^Xl*cpJ zZo_~dl}q0@t~DXEHY!zwGy!^dQu}ynpqq-ZxvGlCRq1$K*L|4ZPArYT{c_LSDrtl! zyYFa(o=QjP>>Na-i&ORJ?8VuE5qg1vYQb$amehj{TkLSdtu=OWdTg0{5KaJA6xKjR z2oJ|(+)}oYPR*>qCJC3p+HW-&vsT%7TG_a28oxL_p42pMHI17E&D{#_V*~~$2EE)? zvC6hQ(~b5JVcQWzkm+c8wqBn&duhVhU$DldfL%P2V;7EU&|HOhd*1DI! z_&cbO<>@lk{^D;h%J5F7y?XPe#9;+(!8jnh056<5lhJ3RGa}rcnV33boG@`^;&*`= zMQko{MP?Hxsc0Na-hiG~56K5rW2RZYOgg##su6XsznUtM?*3$}P#KzPcc-2@F^ZUTHSm1^z%u9wn&<2PKen)}xuZEs88ej|Jy>tDR@em}0CiQnOni>rP8-R`Gb z0n8FDGhun4mG!AfOe3E=KXnco%=@MinaNAd^+uS8X48soPg4q=ptEorW#A|sHrwXu z{2jz35oW!_i{Zl8FmMdS!9C2gI|7uo{*_jIy(`P56@X{3P z(^$_Y{}8MoljDDQRuD+~e^(ZupX)~K!2>5VoC;^BrYGj2=}Y^z9DSib7;V!G=A>lrArgjmoCmsoV)a@RBMw)C!?`9(N&EV;xGQorLmX8 zl@(puw=lOL3(^a%~hz@ zV1tp7Hipr#wSr}$GZY-15v!lQc-v<{W;AA(h)SD?D(dkYYGM;>mg6(l!f~|_efZ7s z-4?Q~)WY%ho)%(6CvD+NpLbd-FJeS(d@>%7pMr=J_^7>>^6$Von2wq_hZwc7%XN+P zE_=@#TaKXALDq~*4C*u>LH&IFYYBDx*n8d&ms)TT0x2X^J5hGeX1D0?#HuuXf7H>L zt(^E9-uZ|{bNQ*!HvCfXm(If733zjUayFW*Pkry?XIEai{Nd%#J^^($wx(I?4PVO^xWk0jhZl9StJALuumv88gu48Na`q)*|kSP0o%wg!7Sb7Ahn*@@|MbKzWlx0hE@xNe0Bp()-g3|FnL0NAYUa_^q)EX4e~ zW9g}|ukAPYO6#5BcDX>eDJ1DOU*BK1FHQVj-R>RQ{1q=K;5NapmmeBkZqJSDrW&u$ zUOGE3$v7f^S{Mr~>x!xXYiC^dnoWv#^DvLn6S98e>pCt^@|^xpAvvTvd#VdAU8lqAJ9|tSXYz(W)4? zDu80s^0_G~f0Y9hEF6t){xoHo)((aR_?<8Q0-hq^tFi0i{CjN$?wiIJe;=f3(#>~Y z?~ZT&k~iSuz21P+=fg=@+|ETa=O(VT09@Rxi+R0V#3BkxB!&% zVYqtpul~KgJ&$jHvFvnCH}AxdU3^8h&s;or?)=#=aYDZP>ARmMhx@xcUO$bHifGo~ z{j~es<}ZG)N9!D-L2w!|2r{Se{MgH@E6p|%Grvu9r|!GC_f7wQD53vLY8?R^ zA=e?0EVpEL$*`@307im_%F7GGzw?1*cW!ppLwslnY|WWeufHwYKp>2A1u-R%18ZA1 z2zZFVv^RxRJuNY+O|`cOCRHM+;6xGdg4?^bA{pYq2bqo-S^yS;SFs^gM-9Oq%lvfT z<&$7rB{)S$Qbvd>sc(mRpW=@6L}Zr6W~v}5yF`bKfCHkn)EMo-V1K zPw;c%wYNm1a|5TnU{OVr1%)D&D?{29P2cT4gd1$q5S`lqADzy|6#`K3?<}@@OG-t9 z#LQASix<@(ORWtN2TL9j*{$}v-JFotK^-A`ta?Y>T)U^vGR6y=58x^GAI62nj$3RI zA8O4I+HTHoGonafdw1?EMUo{)%rl2XX>wB2Q#-L=NPZb_3#TW$>#fYw0Nr23T<&Mx z2oGa>cIW4@XKF|Cv%%|e=$y%j2i?al=!L*^{oD8vg~uk~3WBP<13S@OmP#(qM2fh* z7;STY#T3^BAtv`>O_wtEZr~aSlN@M1@ z&g8HrlOVYR9p6ciNeOhPByp_bz+vzM=RrByXKd$0z`qY{k$n7wd@SSCL8NzaTO;iS z?(A}VYers)@}lA89cy2yiMhjhWJH%k16BYYfHzylrU1JDbW#Beg*j#ZOim8&i5akp z{f`JSXGjn(o5sW9IyY*rg1Y3bxA8b$F5F(m0}n>SASM&`F1VFBgom5q%B|MTW@GC` zWkpTQCf6(k{akZPgl)zg>ETIyY{&Zcc}2PI(#-{<3>RI08A-T1A}JSo@5v>bldr(n(J>7#5b8R%MarJj4EtJ2zU!NfQl%T*r<{7VJ7HwRbOdCd)4dx z1lJFOvu!9COP1nzE~Ir+9%-r+%Ntk8Q}a*?q1xaQy3<+;yBZXZ2+0~4+W->tz{774 zJ0hWfdC<@q-88`Xhw+C?VPn}86xF<-HQ#L9iS9CuFrt)~!7B?p1v#wy3Q=N=HC;k* zJ+0K++sBEk`aZ8X;M|)8ygsWx=W4oLt*X(2f3t-oudRb^#h3(nAjxa35_eh-%Qcb4 zcYBX>qylfcI?(@3{)%PI>Q@8P#-y!G!{7e?o1LU@$AAC$dn1+N$e~iTRxFo}R!gPg zkt3sHMX35mt0zjwyM>)ctCeD@bfk*Fe+2@5sakoyQY_YnD2vFbOQPR;lt(Ql!tx*bO4si6kj`9J642ufYNJ+i{*!p*Y5lMUrXNqbEOH$ zeT|!~`K8sa-2(tC>$*j1z$6hiWuL-d?&{?9dm(P#*f*;>MfHr$JL2!s@3Z{+{0b5% zU&INPiIFN}!3>9;+|1PkU>Q$-Qw3+~Q#A!-(x>TYlJ8XV%ThCd=ePY$pTv(O-*?|k zJf{Z=OjWd|4LFjdrwvOhPW8x6CFv<-w)+@QGv4d>vE;*N1`0@3x21YiKTXopa5`dX zxp3jxh`>&_Z)DO2r&t2!$kNl1NIRI8lYXDhL^=>KdE0lK#P*xEBmFMTmzI~-mkvmp zFa5ocl#{lHHDl$b`P2TV`P1LD{51S^zYeOMXWM-+2MGjd0B7bHGzl~kI4tP|X0%jG zFu?Sv5_qZYP4yLQ$+3JEG$=DGnXQw2VOg^BEQ^%~)SPIpGM~Y?St%f4k^-KS&+4#m zxxWMPUIu#V?1hT6%FV~47{yj~xmikiH)zS$!z}f;@&Pr?w9u~7HNeWv&xH#s$V3Xn zEo|$d0E%rDbl6*X5s-n$L{Nq)-gdjR13(z)_7)!hd4&WD7Tn@;1m-wg2ELLeA3$OI z3=lSK^>l#14lUqI@C%ST$j2q+^GpMyt71*#6W|lRsvJ56ShMR>oI!1IYFBR^x380~ zU@(}no8*xm!i=4QJT+perK*Be9ffWo7a0!n>Abxx1w@yOFZYn|qM>B#7s}*2w?ea% z;%y5KLyE^(+(Dej4CUybkp&U~p=RdliIlAZwI=C#8T3nf{_7RQ!1USuncO_6B*V#_2wu>1^cUJt#bAP?ko zW4YBkVI#-8q}kKs7mc8?@>Gn+P@dlEh83WLV)k8a))%5iXItw)3cq&V#e-fgD6}kd zEo_u7&PUzvDcbQCu>aosrTi{xQfGRvS~P0wOn%@950{R~CZG#!2}X=gtEV-=yQkjR ze#t&_RvLXqlR9!s{Sc39hIS6Wg7*+lH4{2OD;7MyOG}Y$8Xgp#rEq3*mMj$)WmTI3 z+e;40^xN~T+nYBC!8Y9Bxv;X%N?-?hEp)MHL6wbLx=>fFs*N2+IahcAheBwc5CM5d zXQE5r&?P8`+=+@toq9a}aC9PRUj>p=NrEJpUdkly)NU3lKu20!6!VhklC)ARRi~M& zb1l}{XbD!4rDl!}E~&(Y7hm&}^~7Wii{P;0JwMDRxiY;;6ewExVoDd^Ii=?U>l&T@ zk_yPIGJLkol6GeaQekf-k0TqJiju>Nnbd;QWn~r|O{>(su9{II-*H>)c*c&C$f?I1 z|GbwQ%~eAQlzgwz3;4@qD|>(H%<86`sJ!_txZYe1MCr45#K2 zTrS4u&Z4~&Lf`J`Y=q1F4wp-=pyii0u@%D)6m)QyEvCXr`SQ6|53Ik2qg7wmv$JRt zG)N#w2trA2PtiP>StyKW&e1tv(F%(328?#jQ8mKz=lu8OusOn}?GxYgXYZ`dhW+P= zFSrHXs@R-D$=aKQ%YC)Aw2FgLLowZNU6tR6C_J58E9;jD7s1c%{0h&ArV!m?i?C*y zDJcMmmHvu`eZj`w4a2#vS^(MxnTS`-r@?R7hwehSZ0~m0^KWRZOjHJhN3*`I_Sxe& z*5Ar1jO_dd4Y1sjUK>*yTLDwBp`(NJ_TB4vj(coKL*7+A{~!M?D5N_>M1zUIKt=b@ z@H)~1OxZ4qi2ExET)dF{`nje+6}GG#&GR0IN^;tkIVaqozDbOioM6Qd z^o=c@Gf-u3hjo|7#aMFIqJfX^Bgp)i$Oq@_{KlVBuItqr;yK}ZjT%e!aAjLyK>^gQ zRz(}X=N1~#EtDrNt!;g(F9J{gyRX^T&W%{kqKF>o)tg;iGoF-e8}|JEo$kx}aD56l zVCCNbhxA$NGloDI^!AP>F|V!xDcy>!lN5J*+jgy1f@c~ocQl=OWV#nj#IEd?xb#o~ zC}EKuEfWvoV*1<}gu)+Bp!7i~JS8oruZFQCU-~>sq4e|}m%d(JP4cDXrmv4QfBKuY zBYjmMQDm=$!B*IzxVOTQQr6E z%4q4K;p$Vxk?)tQ4;?D;%qLs9dbC&rF;E>n*85Shc&su~DgC@yE0K2SzTf}D_Wlos zuW)6(m2_J;PVO<*7_{FB%&fqu(CiE7EdUGE!+J}{P>eh-h_o&X!$)*ca!e#Z+2iuD zLX#jHB!SF0{`MNRLxB&416>%MD4A2 zNJQYZWfvG1@KR@OT^~p>Dp#dW@W3$oCnQiB_CKOw$kBPd=kZ8bugl_>d^V5>9traS zM$B#LzV=PEXjKrQ-}??O$p5AO1w07#HaCBS$1#C4l;op%Z$oWy5E1Kyw_4rz2mp~n z6M&=s^}iS`18 zSVj$`0VyTRBPXwGpa4;fcaU10@99Ftn9ths%|_J!83Fzl`Z@$hOq22GGnPTlBXX?J z%(3#ap!w9cI3G(kS9oAI*#9ox5yzcsp0!urF$Z<15^ON0m5Lv98i){fcGR!<<%l7w zrB2k@{s}RF%=H`5jlPxvO9ev8x-?E}ajjp$^8lUziO;ris2tH$89AeZe&YTeJ}P;b zwOWAg*o;e9Zq&PP;Pp|}(P=d|ekwm=j`g;&?0BBvYykCd#Fe`%%P}%<#KW3FyS;te zN(oRM-JEaVy-G;$opnJG-osXu9E}K67v2~r@j*Lkn$Rnq`MmLYw65{1I8J@RltY7H ziNgB2?vQ+6)fRZbY-o{bd2QD5l z?;vgtAtU0Rt6G89@n`Jcz~g3R?{cLpR%`fJ9(vMBv`+VA0c@?I(UMd;3sG@-d*@bx zOz%EM5F#NjPnq{(BE4C-qPoh(I~Z0y9<>O1Yv1I(3eqY_z|PIUrPkOM)GX@@8#<^k zyM@He=Zqy_6M%U~3RuKbg`*+#IWQ7E=Nc>j2|1>8-QNN9VO%a{%RH42V4f_M_T%yC;S{3v(!}}NAp+mVm zm=7e<INIr_$!Pjx)E@|95HV?%8uAkc69xk{65zM6Sw{ffjk62BOzCP7yP_w=7Ce;2FFr+ zQwI%i!bQ#`D27{W1X%z}u=93xWnMr6En^Yo#uwx5qHme6*wa9Y!QSR&Z?i1MSPM zjt9fFxP5Ih-|lC(tGW$A%$>bz=Y|7Z4ij{9W054V;+%@}W`)xfX|OqOuRlkMv;M4# zG27f+*Jzo&dtPP1qtpKt9=E51-_^7UnX=i&6YQ}Xw8wT&m>KLTW!_rmbu#ZB^FW0x z_HgFiV^zp4hF|=HaIuXJ4qMUUd}W{lRMw-Re*0CmkL9+or3K6!bu|73fT$SdgS4V) zKPhRpP+g(9C<(GPlT#%aR)N1m9aQM)=h6)A&UAA#y;r!Y*mv_So%TQk+$AsK^M9$l zy+6S{Vul@p?ho+Cv!Z!p4Tb9hnW{kmS|2u?&4^H;NbzCQ$P_`3z3IwiiR-|&D>gUm zqbD9#p6l@71^`N!T`3io)+Cwp!}3#&D>FZ?9zm{@rzI?|9O4Pz94Crpr2|P!`Y~gX zu-kI1SsshYE1I{d#hglheMNH0S!9}>Q_#X`f!4${z^VXGW9jUhtVE8+{U0S^;4IhS zz)6@YIVqJ*Fcn=gcqd`rv=}Qg>6*?!@{-5b*U5+0V#~(usiJVK4(p#4!mR_$l@!ZW zVHKtoW2ednpEe|2y7%vH1q_>2Wc5qUonfX{vspcDS ztk%rQ7O!2|R&w@5*4Qj=z?W4tklCgyi+e<%3-Dbst@c@##a5wZ&KhJvUU_NV|H7DyMm-Rik`#<5dO}YDpbp$MEZ|Tt; zbN4GM=I+-GChmS_JfSKEn{);oNy6R#DuIN%zl9exm$>`uc#XS%Q&^OQyWd!YIr|gt zepO=J{j^$xy09s%z+UeDn}m0{`&kNl5gB*Co@U0~pR#b#Q+p}DkoN;f68``2qqk;qK=?(wrH0zdegH?*8{kGVXp&a>m_%nb072{}p8wcmHE}jJy95 zo|wB|?|lxP`nEm$V(xx{NGW&!14{3GESGFCcfX#IF?T=PT&TA8X{8&2zhJERc@=R0 zcmE90F?at-e0#Y2?IF0!-9Jy_Uhe+K38&osFXJ!tIcWyC`#F!m6gY7APvVQY``^MB zbN6!?vgH7MG}1A5{~P#>yI&*e_hxZ-x%;nL8r=QLo^bbTbtc^XZz@^b{XDT!?tbCk zV(xwo4^TuDbN6$aNmXE{tA>|0G>C)T{Ypu=`zP=w-2H02ardh+DR+NM{+PSpi2N~k zzp@&4zdRXt|7Y=s#@(;|l5zLzEEwSK*TOOGesv__?tc*PE_Z*Mz`eNppCc_W1|(x( zFz)^fD#ykG?tab_VU*miUeGSjPz$B8f2dz!@KtMCzO)AK4X5!s=MRcc)4%=wc6|QY ztPk(-zghnOCx?dkyZ66eU;FcahkxIJ2jJ-;Z+NVah4F89-=0(IuiI%O@WK@`Qk2q| z4DAII2!tV%D0{u!U8dndR0RMPR2@quR-i!4`|NsB54U3%sE57YC^CYtuS=zdoR}0P z1RfV>;2FGOJ^&2L-A&+fPUw}EDj3j+rZEkZ>n@>oTB^`!5JNqlCV}@W0wQ+0dGTd| z!Zr!JmeQJE9b8H#{?ia@5(9U>YD;^ zJZZFe8c#d`j(nO`zyAp?z$%IujV@np5avw85iI8RKF1yL{dt-GU4NZ%ERl4dh25-^p)ZP&#(M4@`ClY|< z^|j=JzF?XX56WCwkBf?1Y@+W8HA1t|-KU5EI*#;C33}=obl%$`#IClHF;N8{)lItC z48D@JV+1I`UTilt+Z$pcgr+5%c$=s2muBUt*b-gY63ABb3mwqyTFoXKTl5M`*mzQS zQ(%0J2CsB%l3lU5y0VO(3nrx}rV&F^8cegCJ=R#4S2j1=5C9{4?8Z+Y*@NnI*QW3Z{oe|UDA7f;R)@Rm?@zO-tRvpNYJsXE`#SAHyxVQS+`_Bb(io~njmIA(`7p?ldQ zXXDh|sGW4gVyPAh08*b~f4@y6j7~b5Y&;zv`eBdlns===5`b>Shg2SJ@H*li8)`4M43?R+4fWsCfdO5w zJ|7t(r!Yd8<9t5cvC;ILh0e|m<$;@4OR~0}$33b+sC6~Bm7X?GzB`Vq%PhHHVU}-O zH?Z^3p0!QFTQM@(fWthe+{aG0<~%|_{m3RsJ5 zzvtJVRK!_M18@=UQSM0@fzWcK`Ohn;rX=R;L%bzXj{gkLa8DU4F6O?M+UqajKPD6N z#vhg!`iNy3TA%20!x#ZU*|btlh*UHW7|8HXgTHSk@oE0&l5k3@cq$36*AoxiUi%PR zgRCGaD@9sSO8ZEEQ&x-{;u1uR0%o&Wdf{}B>58+f-~E-mfwpoWvluoQmaELYTaRUB zs#sA#%Wtz~CcR-`g+mH+w|C1bw+u(iy4G^uICNa;lF%KA_|8>)e#}bMJB459E$zmZ zVOxT(ZGF!}iFK=QQ{)zB5l&dX34fk!-P0IPtOHvsD#-Qgt);ovhHf5=k*qZ4TYc@p zAn&e5cQidQlT=;@RK6@n$D1)v7Hq2=wQ=bFl32Dr`s3OgPv8fgDGra87HbSTuo~~G ztsLh|GjIo)7ApjImqXKFRnxUHf@la2g?J5VF2)L;RF9D|Y0YK+}9*h%xL0ao2=)1sPNEyF``@vWD?Ok{1T!aUHfz+XVnBsz^gt zVBYC+3McEzm5-s$I}ga=%>nnF946Rg)RF|CpuC2Gy&r>5&QJN3U6C#f7ohRrB1#g( zVIW!b50v{ZoI7IUL7|unRl=MqiW@FWwi0=Nr?C5lcU3M>sQOi zijR!dAlf6fKQ>yc5qGROGV<(b@qtQr`0%lEOJ2S;8G$|=L||>MZC3X%U zD?$9nJD2d6VdI`zfvH(nU)~MsC?kxT26&fpxtM?6fOcbmcZGrX^qpBX;ta>9mb!Ty zgY^m}#j#GftKBdPr*#If$pZ&gL-8d_Yg}OVXLvgqQwgVw^J7JFwdr)X$gld{`T-dk zku0OWwqr>6&h%5|aQqph!NTrk8U%Ob@;X-#9C?+rkBC z$T)*2ED2a`_63Jj-~h=b<#7_SkN39G3TM;n_OKZNmk>`zoT5)z9(a7!H~D3K7xYf&9+tDo2NLrP4c>Iz8V{=mCYVg|7{-^h9gdfs zPPna-{UWcFZio-*@wIh9pq_E?dc2dcLuI$Voz3~Y(^)eKld6-8kQ21i-pS4FFfqDi zFe|-z8E?Vi9R)jctI18rQg;@Xc622kdTJCGt zQ20_Wh1Y(PR5q)g^{K8Pbz3yly3SD2U#`-Ib{`8BZA#ocf@k0i?L?>WBYuoT8Sg$p z5%ANHuXhF4>8hZ@`eOhtE}}$$V2$?1$4b{T0KpH*CNOGmD9S5f$ig0An<}U3fWnxM z?8U)7ts6wwme)OxTXFM@!Af{z)krZkhTEqd8F~bzrH%PSMd^#=MH<`oKj5(OZkD|w zFPuB}7TwmARJ(%SjPw(5YQ)NuNAw&{tDsLQ_+~&0t&_xro8Fb^}z(mPR3ul`rJ@8oXH}qX3Qip3GlwzC~g|bp#x5fc;2x*eWdBgYw~? zPi)bif!oYFwBcNnJz`5vv*)r$a+Sl(T9D_Kgq*GqOn9fvhGg_{gyYMN$YEFFuxE35 z&H$b}IQ9mwu$cjZ6(=VKDdp3p5Y1d#hK)g>28qpK_WS%lJmP- zSX7!7x$77$%qq+h;-Ffm)5dzs(GmB0;5XeHJku>b1>YV{!s%$GT;&{PmM{HH!L{@| zB(fPHHCo3#fBPMccaftr7nE`A#x>(_L5PKWtDS6NAYfBtghYlU`;N81qC^xep=YR7XmuopEiZIp)H}buQ-(y@MMT9 zNPjhg@zPaOVgm23Pk3mc5Au5XSP;$Cf-fTq@}<0G8&dmJHQ5Zmd6tsX3sd;wD zSy6{~2e+oy+5p7MLL&@PE}4BR%BnPh#|mVCT&bjSE(}}ED#yAMZ+{hL(v(%zS5q@> z3tQt19=13xKYCIc+`zkGJ_FcJ#?#m1Dcy~B3>;S4VbxDGPFW{zwh?XqYyoDzY&|}p zCTGDoi(9}B(9c%6Ax*g$BfmP29LSPJ!vSHU`%6mYH+9W1qnMil|GRyX&?7($(w=P# zqko;4LVup}Meqt-f%Y0*-Wzfzc72Qw%nnb<1qMU(56tL?e9Y@(32oeWg@BPAM#E;0 z#M-=fbe#^%h9U%-`m?Iaj5fyleR!Rqy`kAL01i`%P$|?ddjOTC!W)!<(+Fuy-sw%r z<++l;=`=0@vuRNx63rmz9XgS~7%e7;_rQ}!Bsd$~s`fVk@ zX?}?pDE>_Ht2eR2>399vfrvCgP`EM%C~CT`amoYf+N;h-m=KcI_lT7Aa&t>7g=Np9 zO;jg^kpFC%03plzR-=w7mJI<(Za>mT+I*fyHb8`W<1sv9F$%nV$nJ3tfF$MZF*T) zEOQVSOqj5!W(ly`IfbXH_EjN>8IFGYBSP@(H12?d?(F=Dastn-M$J26_Z33k)<@bO zfj(tTw{C{$3)VuFSVPX;7S7mYxxRa}I$Ek!Yd`3E)ne(9DqA{YP~qV{0?{y#Z1#NUDce*KA&{zrNKpB?gt|F*lsBSyFG1VyGXw#jQWgo23$Ronu$3S?%cv-29+ifD3f z_b#dlZeFBUkt{-jhYW=U`W>6TbrV+~-q4ln^%imMQu5R}v>ehoNRli!1)4LM-&t=G zaC&ocfzFXZqS)?_2o|y39GcD$Y^%!T8SfD&&4SrLtF<^CAWfO15R7omsITJyuV%_zNQN}&dG z9_{soXh{Vvy(JICS1VL+(94nMd zHYu6&JSkwHA}jf!-F((&`<8u}eEa0CkK^`BEw%FO3+p+1*_WV|FYD93^YXpEu*?H( zv0w`ATQBaJ>!2?!&W0gNwF0uD%x7KBhQ{LT3rnzmTPc}isaZZN)VgeOmd}D&y*BLw zt+#wx9C+DeW!Ps~g88ywR%qtS+G1^9*k9B@dD&+N`LcOFC^c(F>`R|+`=>Q)apoHs zkb?#(Yo{&GtW&mCvWD4QSpnG>1C7n5&OWm*vhoHpThLZIN6+3lu!L-yvZZiP0a>b5 zZaufSQ!3Pa)&lccj|NJy1pCYi7#J|?!ZW+=vwW5%`^#9|5g<5Ud z;8+1R5azQ4Tblz78fg7}1g*Txu?F4qGs}0+RBLnA!L0QIUu0ddu3D;nJCM(UmO0Cp z#hEV~T?+yxa`qXq=-@NZa^2I(hT)!B;)JA{gK~MUkZBEFWpF|1>g?bz_ytTe0z%Fj zHO-aquj?57rEto;PmwDCJk-r-HWl)IZe?57G=P>shg;Fz(}e7;ityfC2#d#2B6t^} z4T6FXXK?hY+%Z0yEN$8UA7{NfzOc?IiV}S>Jfq3yeuKSi8pfTP* zXXT!e!-5N3z_x_a0Qiw8YkZwz-JjzGkK+`(;3@T53U~N|N3)ADExil4-*@R9;JYjg zersR6p4ofz4TcBHNyBMAJ!JNNFGycuVP^C@n68J=-u!7fX}N!>-?Tk{sPez*a?^Pl z9KUreW9`g^bM z)AY2SG@SmX)T=Z+_?yG${Q$G!3owl6K`+uyHVFMqi4d9e1_ zgAbJsA0H_lJyktCTpArNl}CmT4a192JUUwa8?)uglhxv36a#k86y~uMj72C&VIND8!tXZRDG8elsD9YT5)Og$mk z<_D|Nme$@7aRFk}tzv zlzroq_XO1E%BG_!|Gd1sU}2q8lh9VzUe}|Ek8Z_85p-`g=Z)pN7AwuZMRFkG`|uBO z@`j^4qK{qh>}K!FbZOgrfCo?Dz9|Q$@8mr|?SZ@X3%R_cN#W#&?j%g9UITFv1!HW1 z2Oo_`dWxxu=%8w$f4pv7EJbyw=s2zAyVv*-4w?3*7|W~bTon{T&h7FBR=Kg#R34%? z*Lk{tq4(f)k8=-eUVY1mxG!d1ca#HF>p#0o`S77Q=RW^FF|fF-bl*sxn_`Ps63Um} z5K&;`HF6X?c7Z{U(U1;%xu0$DhL4Gd&c-K6V!~#%qR-IZ($#t?iS;RW)She#Co&)S zOrln5ALGY#`r1u?yFA8n$3!!`dyk2%m9maAQ8k~uE-NHSJaEyJ0wSqHX?XI2}fN&L?L9@16#_YGB>;V zG?VFd^Kuvuku0DHPt&+5QYTX%~%M@lV}; zE|~irb6sy?Ia=y#!ccMA2p2ZAilDJYxB7asBW<-5E;nY4ecuW4t(yz2nMQb*$F*!L zqV0|~o-07wF}LFbOf9@oR0A2v z+cC5QEPTsb)A|DRei*?=rPcEjIkU;K>M!CEGipD6r^bXgSs_4TAha$(C0LC%Cn<)l zTQ|LXeph%4&y4=DRodN`3A$Ta&B#%RZ*mrI5fx~?bQ$!tJr4D>(aPOa33tk)l4?Rs z7wjYC5)Wt2g?whKCS^8GR}rt916S*_nw6q$XBNm3dT+ZgQ4T8W)_N?eyt4_o2t&CM zD(#oL?U%ak_geBxjTWXx`=v(vWwiFiyH2!xS39@t=347I6`*~uM2o0F+*UhKgxA(A z7K|sX+*5P%rZKbFW!2@d#c?w-6U}I}UWI{s0nNP{NlvC)Ve__p*sH$Pm|d{r0_~ff z#ssmB$x!&Fy2?;PzNEQejhFL)92CH>to2x63H8<~+zIDb8|Xm(DaoiS?u0kPOi^6UCv4*n;gUvbPhmklG((?aK&i0*brF` zyDbvLRW}=2Psj(gSdI=~T*xZ8LrjbK_&G`J_pRht(`WG#!a7M&W)=crI857g7VO3& zy%}$`E(j^ndZP{9tD^4YoJZwoqGCrwYzdl&g|2Qqge6y{yi^AiIINpt^OtNYwdz?p z=Ho<4Y`|F1oSuYAMJ#?b`K9d^))QCpEH(Sxcs)(-`T-sm)NRbS8)XoV#x-~q%|Iwf{)JYvxn`Y#>_(SO%qeE1jPB3@4b?J? z(RL!F_Ye#P7Vf5ZOE(o%&|0yiG=;Td;q-7p(&%nJzNzQKSiPl-NsguoR2Z)aYoyuN z+3PQ>=_Y04JdW3Fi#QyV$#OA4EzBE8>`UFXE7~o}=OVPqzECM(irXf-;P*6{$m(`X zQ;x&+l`~bo4!0X847!5b{nznIISefl?+8%Hj})VQ>>B|Yoh>YO&7Tf_)VkjlGD$1Y zbLJxx0P=TE93OrZ<9xMhD>SsqfGu$16R*`c~<2^!`_e zOWz+ZmZnOjqr>H2RzJm@-&hH=fX|K~27qON%F&X-mxrsvPn9Y^L6qR36VFr+m7c)# zA8G~PEtW=3AFT{OP<|N0fcE}>ZfJ?Z|qoX*cN~ zKR%Ai3e(50a9HJgQiC45lbhNccVRW`o>V#t@*7Q)zOsAIX4dZlbF$QZQ{Vzj%0?#qsg4pFOEi4e9TyTka&yL{6G6H%Shj5cP7LqB%| zhF@bgN4BxuF{Y-94)zE*ELWE3S0Dy14vbxAAebdEY(Zf6(~--3?FddBu>lLJ3aiC> zIqfYBIBIV&E9~Xn1a@N(WRnB4AchWM&oiqq{Eu3~tH z2OwhIt(C2LBJ-oUaI22T&*c`4HR}P#59`hFrm4S1s%~|Dsj;JhE5i1^At+YTaV<LDJ4W zyLu5=TW)L!q~m=Py_l@>?vtr!Iq?7--89K+nunFJHIpFb0^x?Mm)1I>y(hRmo-cd7R4~H|i zF8nCXu*+ItH1aoBmqIp4f7XJiTevA!E;!t26RdOVT1SN#<}g`Alf|Wx&1h*|uU5YY zya5+ZzB9YfSPYw6e?|~fJGVGBbe8z*>WXtxj+y5rX@SREn>7-`FN?L5)*p7%RvQt?#Hzib{0%~GO)0U0jH(JAgeSNkl>g%u4 zuS)+#jX+mtN?A|`(;sVjjx96X)ty=c6m4&6e*kPRn{hGL0z_on^Ls)@^GggP50mLQ<$@$(nDaSW~k`vN@8HpOw#2t$kURthOvJ^SQ;9Ma&w& zQMS0D_YlCz+UmM!xkZQLtKIlhylmHHW1D3;6EcUY%nV*`Sl5Gru>lJ|26Qq${TMxF zne8;zCNbHBz-}V#$%N})KFi0D<>FKh2tX-0Rwd_slG*YpZo~>OXZ>*{KZ!H!V8R4j z2OFydQ0LaVZSq9bjW?9TcNW&{A%WcT=S1wei&bJA1pgG;sn43d5t(QZ=OUb$?NEF>68 z*QGrt;o4i$M_vU$XO&k1+DH~6E0(pp5`_}u%Db34Q?|G>;1Zrzl}lwvR&t%Z${Frf1q;_*AiMvO6!j--@NkpNTSYJ5s#Way$Iq>+8a zv>)>1S!pa8D#wgf=1MW-2=vhC^tBiOOzwaWT5K5X0;BM4F8PJeGwvl~!H7t@;DKQ7!tMUi4q;=Y8Eh5E&dqozmA;T_1x?gSnfzxw#G3 zu3fwLy$NI|kLgt|1p9`GNsShfZhRm}xf?n6$3cfvtTXW@OyR<(m_D7{s|3J@O z`wD@LSF6*X60NTwN@=vDTff}8p&LP|GvGJ=K0(D+b9SK-K{iTd&0-s4MK;FrATLiJ z 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 literal 0 HcmV?d00001 From d8829f22418e30959bac8822fae168cb398554d6 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Tue, 17 Mar 2026 09:03:59 +0100 Subject: [PATCH 47/58] fix: HTML scraper false positives from URL keyword matching and junk titles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Include keywords now match title only, not the URL — the feed URL path (e.g. /desaparecidos) was letting every link on the page pass the filter. Added junk title blocklist to reject navigation boilerplate (load more, cookie config, browser names) at parse time. --- internal/collector/parse/html.go | 25 ++++++++++++++++++++++++- internal/collector/run/run.go | 11 ++++++++--- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/internal/collector/parse/html.go b/internal/collector/parse/html.go index af7f962..86b207c 100644 --- a/internal/collector/parse/html.go +++ b/internal/collector/parse/html.go @@ -14,6 +14,29 @@ var anchorRe = regexp.MustCompile(`(?is)]*href=["']([^"']+)["'][^>]*>([\s var tagStripRe = regexp.MustCompile(`(?is)<[^>]+>`) var scriptStripRe = regexp.MustCompile(`(?is)|`) +// junkTitles are navigation / boilerplate link texts that should never +// become alerts. Checked case-insensitively against the stripped title. +var junkTitles = []string{ + "load more", "read more", "see more", "show more", "ver más", + "cookie", "cookies", "privacy policy", "terms of use", + "terms of service", "legal notice", "aviso legal", + "log in", "sign in", "register", "iniciar sesión", + "contact us", "about us", "home", "back to top", + "next", "previous", "page", "skip to content", + "accept", "decline", "configuración de cookies", + "mozilla firefox", "google chrome", "microsoft edge", +} + +func isJunkTitle(title string) bool { + lower := strings.ToLower(title) + for _, junk := range junkTitles { + if lower == junk || strings.TrimSpace(lower) == junk { + return true + } + } + return false +} + func ParseHTMLAnchors(body string, baseURL string) []FeedItem { matches := anchorRe.FindAllStringSubmatch(body, -1) seen := make(map[string]struct{}, len(matches)) @@ -35,7 +58,7 @@ func ParseHTMLAnchors(body string, baseURL string) []FeedItem { continue } title := StripHTML(match[2]) - if len(title) < 8 { + if len(title) < 8 || isJunkTitle(title) { continue } finalURL := resolved.ResolveReference(link).String() diff --git a/internal/collector/run/run.go b/internal/collector/run/run.go index 06175a8..11ee0a6 100644 --- a/internal/collector/run/run.go +++ b/internal/collector/run/run.go @@ -677,11 +677,16 @@ func filterKeywords(items []parse.FeedItem, include []string, exclude []string) exclude = normalizeKeywords(exclude) out := []parse.FeedItem{} for _, item := range items { - hay := strings.ToLower(item.Title + " " + item.Link) - if len(include) > 0 && !containsKeyword(hay, include) { + titleHay := strings.ToLower(item.Title) + fullHay := strings.ToLower(item.Title + " " + item.Link) + // Include keywords match against title only — matching against the + // URL caused false positives when the page URL itself contained a + // keyword (e.g. /desaparecidos in the path let every link through). + if len(include) > 0 && !containsKeyword(titleHay, include) { continue } - if len(exclude) > 0 && containsKeyword(hay, exclude) { + // Exclude keywords match against title + URL (conservative). + if len(exclude) > 0 && containsKeyword(fullHay, exclude) { continue } out = append(out, item) From bc173ca3dd8af6321345985339d0e796fd274be5 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Tue, 17 Mar 2026 09:24:04 +0100 Subject: [PATCH 48/58] feat: add maritime security, legislative, and conflict monitoring sources New categories: maritime_security (7 sources incl. US Navy, CIMSEC, EU NAVFOR, MARAD) and legislative (7 sources incl. EU Parliament, EU Council, EEAS, US Congress, State Dept). Additional conflict monitoring sources: US DoD, NATO, OSCE, UN Security Council, ICG, German Foreign Office, France Diplomatie. All filtered with include_keywords to reduce noise. Gap analysis now discovers these categories automatically for all target countries. --- internal/collector/discover/gap.go | 15 + internal/collector/discover/gap_test.go | 14 +- registry/source_registry.json | 385 ++++++++++++++++++++++++ src/index.css | 2 + src/lib/severity.ts | 8 + src/types/alert.ts | 4 +- 6 files changed, 420 insertions(+), 8 deletions(-) diff --git a/internal/collector/discover/gap.go b/internal/collector/discover/gap.go index 4938952..ea0231b 100644 --- a/internal/collector/discover/gap.go +++ b/internal/collector/discover/gap.go @@ -32,6 +32,9 @@ var expandedCategories = []string{ "travel_warning", "intelligence_report", "fraud_alert", + "legislative", + "conflict_monitoring", + "maritime_security", } // targetCountries lists all countries the system should cover with at least @@ -287,6 +290,12 @@ func gapAuthorityLabel(country string, category string) string { return country + " financial regulator or central bank" case "wanted_suspect": return country + " wanted persons" + case "legislative": + return country + " parliament or foreign affairs ministry" + case "conflict_monitoring": + return country + " defense ministry or armed forces" + case "maritime_security": + return country + " coast guard or maritime authority" default: return country + " " + strings.ReplaceAll(category, "_", " ") } @@ -304,6 +313,12 @@ func gapAuthorityType(category string) string { return "national_security" case "fraud_alert": return "regulatory" + case "legislative": + return "regulatory" + case "conflict_monitoring": + return "national_security" + case "maritime_security": + return "national_security" default: return "government" } diff --git a/internal/collector/discover/gap_test.go b/internal/collector/discover/gap_test.go index 9f5b41f..5e77093 100644 --- a/internal/collector/discover/gap_test.go +++ b/internal/collector/discover/gap_test.go @@ -11,13 +11,13 @@ import ( ) func TestAnalyzeGaps_FindsMissing(t *testing.T) { - // A registry with only Germany cyber_advisory — everything else is a gap. - sources := []model.RegistrySource{ - {Category: "cyber_advisory", Source: model.SourceMetadata{CountryCode: "DE"}}, - {Category: "public_appeal", Source: model.SourceMetadata{CountryCode: "DE"}}, - {Category: "travel_warning", Source: model.SourceMetadata{CountryCode: "DE"}}, - {Category: "intelligence_report", Source: model.SourceMetadata{CountryCode: "DE"}}, - {Category: "fraud_alert", Source: model.SourceMetadata{CountryCode: "DE"}}, + // A registry covering all expanded categories for Germany — everything else is a gap. + var sources []model.RegistrySource + for _, cat := range expandedCategories { + sources = append(sources, model.RegistrySource{ + Category: cat, + Source: model.SourceMetadata{CountryCode: "DE"}, + }) } var buf bytes.Buffer diff --git a/registry/source_registry.json b/registry/source_registry.json index e0edbb5..565c2ed 100644 --- a/registry/source_registry.json +++ b/registry/source_registry.json @@ -5832,5 +5832,390 @@ "lat": 48.86, "lng": 2.32, "include_keywords": ["outbreak", "avian", "influenza", "disease", "epidemic", "zoonotic", "virus", "pathogen", "infection", "surveillance", "alert", "emergency"] + }, + + {"_comment": "═══════════════ MARITIME SECURITY ═══════════════"}, + + { + "type": "rss", + "source": { + "source_id": "us-navy-news", + "authority_name": "US Navy News", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "national_security", + "base_url": "https://www.navy.mil" + }, + "feed_url": "https://www.navy.mil/DesktopModules/ArticleCS/RSS.ashx?ContentType=1&Site=1&max=10", + "category": "maritime_security", + "region_tag": "US", + "lat": 38.87, + "lng": -77.01, + "include_keywords": ["piracy", "maritime", "shipping", "vessel", "naval", "fleet", "strait", "gulf", "houthi", "red sea", "patrol", "intercept", "seizure", "smuggling", "freedom of navigation"] + }, + { + "type": "rss", + "source": { + "source_id": "cimsec", + "authority_name": "CIMSEC", + "country": "United States", + "country_code": "US", + "region": "International", + "authority_type": "regulatory", + "base_url": "https://cimsec.org" + }, + "feed_url": "https://cimsec.org/feed/", + "category": "maritime_security", + "region_tag": "INT", + "lat": 38.87, + "lng": -77.01, + "include_keywords": ["piracy", "maritime security", "shipping", "naval", "strait", "chokepoint", "attack", "vessel", "threat", "patrol", "red sea", "gulf", "houthi", "mine", "boarding"] + }, + { + "type": "rss", + "source": { + "source_id": "gcaptain", + "authority_name": "gCaptain Maritime News", + "country": "United States", + "country_code": "US", + "region": "International", + "authority_type": "private_sector", + "base_url": "https://gcaptain.com" + }, + "feed_url": "https://gcaptain.com/feed/", + "category": "maritime_security", + "region_tag": "INT", + "lat": 37.77, + "lng": -122.42, + "include_keywords": ["piracy", "attack", "seized", "hijack", "missile", "houthi", "drone strike", "maritime security", "boarding", "smuggling", "sanctions", "detained", "navy", "warship", "patrol", "red sea", "gulf of aden", "strait of hormuz", "malacca"] + }, + { + "type": "rss", + "source": { + "source_id": "hellenicshipping-piracy", + "authority_name": "Hellenic Shipping News — Piracy", + "country": "Greece", + "country_code": "GR", + "region": "International", + "authority_type": "private_sector", + "base_url": "https://www.hellenicshippingnews.com" + }, + "feed_url": "https://www.hellenicshippingnews.com/category/piracy-and-security-news/feed/", + "category": "maritime_security", + "region_tag": "INT", + "lat": 37.94, + "lng": 23.65 + }, + { + "type": "rss", + "source": { + "source_id": "maritime-executive", + "authority_name": "Maritime Executive", + "country": "United States", + "country_code": "US", + "region": "International", + "authority_type": "private_sector", + "base_url": "https://maritime-executive.com" + }, + "feed_url": "https://maritime-executive.com/feed", + "category": "maritime_security", + "region_tag": "INT", + "lat": 33.77, + "lng": -118.19, + "include_keywords": ["piracy", "attack", "seized", "hijack", "missile", "houthi", "security", "boarding", "smuggling", "sanctions", "detained", "navy", "warship", "patrol", "collision", "grounding", "sinking", "rescue"] + }, + { + "type": "html-list", + "followRedirects": true, + "source": { + "source_id": "eunavfor", + "authority_name": "EU NAVFOR Atalanta", + "country": "European Union", + "country_code": "EU", + "region": "Europe", + "authority_type": "national_security", + "base_url": "https://eunavfor.eu" + }, + "feed_url": "https://eunavfor.eu/news", + "category": "maritime_security", + "region_tag": "EU", + "lat": 11.59, + "lng": 43.15, + "include_keywords": ["piracy", "operation", "vessel", "patrol", "escort", "maritime", "incident", "seized", "rescue", "suspicious", "attack", "atalanta", "aspides"] + }, + { + "type": "html-list", + "followRedirects": true, + "source": { + "source_id": "marad-advisories", + "authority_name": "US MARAD Maritime Advisories", + "country": "United States", + "country_code": "US", + "region": "International", + "authority_type": "regulatory", + "base_url": "https://www.maritime.dot.gov" + }, + "feed_url": "https://www.maritime.dot.gov/msci-advisories", + "category": "maritime_security", + "region_tag": "INT", + "lat": 38.88, + "lng": -77.02, + "include_keywords": ["advisory", "threat", "piracy", "attack", "vessel", "maritime", "security", "warning", "alert", "strait", "gulf", "red sea"] + }, + + {"_comment": "═══════════════ LEGISLATIVE / POLITICAL OSINT ═══════════════"}, + + { + "type": "rss", + "source": { + "source_id": "eu-parliament-press", + "authority_name": "European Parliament Press", + "country": "European Union", + "country_code": "EU", + "region": "Europe", + "authority_type": "regulatory", + "base_url": "https://www.europarl.europa.eu" + }, + "feed_url": "https://www.europarl.europa.eu/rss/doc/press-releases/en", + "category": "legislative", + "region_tag": "EU", + "lat": 48.60, + "lng": 7.77, + "include_keywords": ["sanction", "defence", "defense", "security", "border", "migration", "terrorism", "cyber", "intelligence", "military", "war", "conflict", "foreign affairs", "resolution", "embargo", "arms", "threat", "crisis", "nato"] + }, + { + "type": "rss", + "source": { + "source_id": "eu-council-press", + "authority_name": "Council of the EU Press", + "country": "European Union", + "country_code": "EU", + "region": "Europe", + "authority_type": "regulatory", + "base_url": "https://www.consilium.europa.eu" + }, + "feed_url": "https://www.consilium.europa.eu/en/press/press-releases/rss.xml", + "category": "legislative", + "region_tag": "EU", + "lat": 50.84, + "lng": 4.37, + "include_keywords": ["sanction", "defence", "defense", "security", "border", "migration", "terrorism", "cyber", "intelligence", "military", "war", "conflict", "foreign", "resolution", "embargo", "arms", "threat", "crisis", "restrictive measures"] + }, + { + "type": "rss", + "source": { + "source_id": "eeas-press", + "authority_name": "EU External Action Service", + "country": "European Union", + "country_code": "EU", + "region": "Europe", + "authority_type": "national_security", + "base_url": "https://www.eeas.europa.eu" + }, + "feed_url": "https://www.eeas.europa.eu/eeas/press-material_en?f%5B0%5D=press_material_type%3APress+release&_format=rss", + "category": "legislative", + "region_tag": "EU", + "lat": 50.84, + "lng": 4.38, + "include_keywords": ["sanction", "security", "defence", "defense", "conflict", "military", "war", "crisis", "terrorism", "foreign", "humanitarian", "ceasefire", "peace", "threat", "arms", "embargo", "nato", "statement"] + }, + { + "type": "rss", + "source": { + "source_id": "eu-commission-press", + "authority_name": "European Commission Press", + "country": "European Union", + "country_code": "EU", + "region": "Europe", + "authority_type": "regulatory", + "base_url": "https://ec.europa.eu" + }, + "feed_url": "https://ec.europa.eu/commission/presscorner/api/rss", + "category": "legislative", + "region_tag": "EU", + "lat": 50.84, + "lng": 4.38, + "include_keywords": ["sanction", "security", "defence", "defense", "border", "migration", "terrorism", "cyber", "military", "crisis", "threat", "embargo", "arms", "restrictive measures", "disinformation"] + }, + { + "type": "rss", + "source": { + "source_id": "uk-parliament-lords", + "authority_name": "UK Parliament — Lords", + "country": "United Kingdom", + "country_code": "GB", + "region": "Europe", + "authority_type": "regulatory", + "base_url": "https://www.parliament.uk" + }, + "feed_url": "https://lordsbusiness.parliament.uk/ItemOfBusiness/atom", + "category": "legislative", + "region_tag": "GB", + "lat": 51.50, + "lng": -0.12, + "include_keywords": ["sanction", "security", "defence", "defense", "border", "migration", "terrorism", "cyber", "intelligence", "military", "war", "conflict", "foreign affairs", "arms", "threat", "crisis", "nato"] + }, + { + "type": "rss", + "source": { + "source_id": "us-congress-bills", + "authority_name": "US Congress — Bills", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "regulatory", + "base_url": "https://www.congress.gov" + }, + "feed_url": "https://www.congress.gov/rss/most-viewed-bills.xml", + "category": "legislative", + "region_tag": "US", + "lat": 38.89, + "lng": -77.01, + "include_keywords": ["sanction", "security", "defense", "border", "immigration", "terrorism", "cyber", "intelligence", "military", "war", "conflict", "foreign", "arms", "threat", "national defense", "nato", "maritime"] + }, + { + "type": "rss", + "source": { + "source_id": "us-state-dept-press", + "authority_name": "US State Department Press", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "national_security", + "base_url": "https://www.state.gov" + }, + "feed_url": "https://www.state.gov/rss-feed/press-releases/feed/", + "category": "legislative", + "region_tag": "US", + "lat": 38.89, + "lng": -77.05, + "include_keywords": ["sanction", "security", "defense", "terrorism", "conflict", "war", "crisis", "ceasefire", "peace", "threat", "arms", "embargo", "nuclear", "nato", "humanitarian", "statement"] + }, + { + "type": "rss", + "source": { + "source_id": "us-dod-press", + "authority_name": "US Department of Defense", + "country": "United States", + "country_code": "US", + "region": "North America", + "authority_type": "national_security", + "base_url": "https://www.defense.gov" + }, + "feed_url": "https://www.defense.gov/DesktopModules/ArticleCS/RSS.ashx?max=10&ContentType=1&Site=945", + "category": "conflict_monitoring", + "region_tag": "US", + "lat": 38.87, + "lng": -77.06, + "include_keywords": ["operation", "strike", "deploy", "missile", "threat", "conflict", "attack", "defense", "military", "patrol", "exercise", "nato", "coalition", "airstrike", "maritime"] + }, + { + "type": "rss", + "source": { + "source_id": "nato-news", + "authority_name": "NATO News", + "country": "International", + "country_code": "INT", + "region": "International", + "authority_type": "national_security", + "base_url": "https://www.nato.int" + }, + "feed_url": "https://www.nato.int/cps/en/natolive/news.xml", + "category": "conflict_monitoring", + "region_tag": "INT", + "lat": 50.88, + "lng": 4.42, + "include_keywords": ["security", "defence", "defense", "military", "operation", "deploy", "threat", "conflict", "exercise", "summit", "alliance", "deterrence", "cyber", "maritime", "air", "nuclear"] + }, + { + "type": "rss", + "source": { + "source_id": "osce-press", + "authority_name": "OSCE Press", + "country": "International", + "country_code": "INT", + "region": "Europe", + "authority_type": "regulatory", + "base_url": "https://www.osce.org" + }, + "feed_url": "https://www.osce.org/rss.xml", + "category": "conflict_monitoring", + "region_tag": "INT", + "lat": 48.21, + "lng": 16.37, + "include_keywords": ["conflict", "security", "election", "monitoring", "border", "ceasefire", "crisis", "military", "weapons", "arms", "human rights", "detention", "freedom", "threat"] + }, + { + "type": "rss", + "source": { + "source_id": "un-security-council", + "authority_name": "UN Security Council", + "country": "International", + "country_code": "INT", + "region": "International", + "authority_type": "regulatory", + "base_url": "https://press.un.org" + }, + "feed_url": "https://press.un.org/en/taxonomy/term/10/feed", + "category": "conflict_monitoring", + "region_tag": "INT", + "lat": 40.75, + "lng": -73.97, + "include_keywords": ["sanction", "resolution", "conflict", "security", "peace", "ceasefire", "military", "threat", "war", "humanitarian", "arms", "embargo", "nuclear", "terrorism"] + }, + { + "type": "rss", + "source": { + "source_id": "icg-crisiswatch", + "authority_name": "International Crisis Group", + "country": "International", + "country_code": "INT", + "region": "International", + "authority_type": "regulatory", + "base_url": "https://www.crisisgroup.org" + }, + "feed_url": "https://www.crisisgroup.org/crisiswatch/feed", + "category": "conflict_monitoring", + "region_tag": "INT", + "lat": 50.84, + "lng": 4.36, + "include_keywords": ["conflict", "crisis", "war", "violence", "tension", "ceasefire", "peace", "military", "insurgency", "coup", "protest", "clashes", "escalation", "deteriorat"] + }, + { + "type": "rss", + "source": { + "source_id": "de-auswaertiges-amt", + "authority_name": "German Foreign Office", + "country": "Germany", + "country_code": "DE", + "region": "Europe", + "authority_type": "national_security", + "base_url": "https://www.auswaertiges-amt.de" + }, + "feed_url": "https://www.auswaertiges-amt.de/en/rss/news-feed.xml", + "category": "legislative", + "region_tag": "DE", + "lat": 52.52, + "lng": 13.38, + "include_keywords": ["sanction", "security", "conflict", "crisis", "military", "war", "terrorism", "defence", "defense", "nato", "humanitarian", "ceasefire", "peace", "threat", "arms", "embargo", "nuclear"] + }, + { + "type": "rss", + "source": { + "source_id": "fr-diplomatie", + "authority_name": "France Diplomatie", + "country": "France", + "country_code": "FR", + "region": "Europe", + "authority_type": "national_security", + "base_url": "https://www.diplomatie.gouv.fr" + }, + "feed_url": "https://www.diplomatie.gouv.fr/en/rss/", + "category": "legislative", + "region_tag": "FR", + "lat": 48.86, + "lng": 2.32, + "include_keywords": ["sanction", "security", "conflict", "crisis", "military", "war", "terrorism", "defence", "defense", "nato", "humanitarian", "ceasefire", "peace", "threat", "arms"] } ] diff --git a/src/index.css b/src/index.css index c075041..bc78fe2 100644 --- a/src/index.css +++ b/src/index.css @@ -46,6 +46,8 @@ --color-cat-emergency: #b85c4a; --color-cat-environment: #4a8b6e; --color-cat-disease: #c45e8a; + --color-cat-maritime: #2a7a9b; + --color-cat-legislative: #6b7f45; } * { diff --git a/src/lib/severity.ts b/src/lib/severity.ts index d2691ab..3586add 100644 --- a/src/lib/severity.ts +++ b/src/lib/severity.ts @@ -55,6 +55,8 @@ export const categoryLabels: Record = { emergency_management: "Emergency Management", environmental_disaster: "Environmental Disaster", disease_outbreak: "Disease Outbreak", + maritime_security: "Maritime Security", + legislative: "Legislative", }; export const categoryOrder: AlertCategory[] = [ @@ -77,6 +79,8 @@ export const categoryOrder: AlertCategory[] = [ "emergency_management", "environmental_disaster", "disease_outbreak", + "maritime_security", + "legislative", ]; /** @@ -103,6 +107,8 @@ export const categoryBadge: Record = { emergency_management: "bg-cat-emergency/15 text-cat-emergency border-cat-emergency/30", environmental_disaster: "bg-cat-environment/15 text-cat-environment border-cat-environment/30", disease_outbreak: "bg-cat-disease/15 text-cat-disease border-cat-disease/30", + maritime_security: "bg-cat-maritime/15 text-cat-maritime border-cat-maritime/30", + legislative: "bg-cat-legislative/15 text-cat-legislative border-cat-legislative/30", }; export const categoryIcons: Record = { @@ -125,6 +131,8 @@ export const categoryIcons: Record = { emergency_management: "Siren", environmental_disaster: "CloudRain", disease_outbreak: "Bug", + maritime_security: "Anchor", + legislative: "Landmark", }; export function freshnessLabel(hours: number): string { diff --git a/src/types/alert.ts b/src/types/alert.ts index b3ab794..ac1c3b5 100644 --- a/src/types/alert.ts +++ b/src/types/alert.ts @@ -25,7 +25,9 @@ export type AlertCategory = | "intelligence_report" | "emergency_management" | "environmental_disaster" - | "disease_outbreak"; + | "disease_outbreak" + | "maritime_security" + | "legislative"; export type AuthorityType = | "police" | "national_security" From f723bdcd91f8887f49149dbd299a3d512cce3d7b Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Tue, 17 Mar 2026 09:46:28 +0100 Subject: [PATCH 49/58] =?UTF-8?q?chore:=20reject=20European=20Schoolnet=20?= =?UTF-8?q?=E2=80=94=20educational,=20not=20intelligence?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add non-OSINT term and host blocklists to discovery hygiene (education, world bank, social media, entertainment, etc). Purge orphan alerts from rejected/removed sources on each collection cycle. Explicitly reject worldbank-education-digital in registry. --- internal/collector/discover/hygiene.go | 55 +++++++++++++++++++++++++- internal/collector/run/run.go | 25 ++++++++++++ registry/source_registry.json | 19 +++++++++ 3 files changed, 98 insertions(+), 1 deletion(-) diff --git a/internal/collector/discover/hygiene.go b/internal/collector/discover/hygiene.go index 2a918a6..2406d09 100644 --- a/internal/collector/discover/hygiene.go +++ b/internal/collector/discover/hygiene.go @@ -30,6 +30,40 @@ var genericNewsroomTerms = []string{ "communications office", } +// nonOSINTTerms catches organizations that have no intelligence relevance. +// Matched against lowered name and hostname. +var nonOSINTTerms = []string{ + "school", "university", "college", "academy", "education", + "world bank", "imf", "monetary fund", + "library", "museum", "archive", + "tourism", "tourist", "travel agency", + "sport", "olympic", "football", "soccer", "fifa", + "entertainment", "oscars", "grammy", "billboard", + "recipe", "cooking", "food network", + "weather forecast", "meteorolog", + "real estate", "property", + "fashion", "beauty", "lifestyle", + "church", "mosque", "synagogue", "cathedral", + "kindergarten", "daycare", "nursery", + "zoo", "aquarium", "botanical", + "lottery", "casino", "gambling", + "dating", "matrimon", +} + +// nonOSINTHosts rejects entire domains that are never OSINT-relevant. +var nonOSINTHosts = []string{ + "worldbank.org", "imf.org", + "unesco.org", "unicef.org", + "wikipedia.org", "wiktionary.org", + "facebook.com", "twitter.com", "x.com", "instagram.com", + "youtube.com", "tiktok.com", "reddit.com", + "linkedin.com", "pinterest.com", + "amazon.com", "ebay.com", "alibaba.com", + "spotify.com", "netflix.com", + "stackoverflow.com", "github.com", + "schoolnet.eu", "european-schoolnet", +} + func passesDiscoveryHygiene(name string, website string, authorityType string) bool { name = strings.ToLower(strings.TrimSpace(name)) authorityType = strings.ToLower(strings.TrimSpace(authorityType)) @@ -41,6 +75,11 @@ func passesDiscoveryHygiene(name string, website string, authorityType string) b return false } } + for _, term := range nonOSINTTerms { + if strings.Contains(name, term) { + return false + } + } if authorityType == "police" { for _, term := range genericNewsroomTerms { if strings.Contains(name, term) { @@ -48,7 +87,7 @@ func passesDiscoveryHygiene(name string, website string, authorityType string) b } } } - if hostLooksLocal(website) { + if hostLooksLocal(website) || hostIsNonOSINT(website) { return false } return true @@ -70,3 +109,17 @@ func hostLooksLocal(rawURL string) bool { strings.Contains(host, ".county.") || strings.Contains(host, ".municipal.") } + +func hostIsNonOSINT(rawURL string) bool { + parsed, err := url.Parse(strings.TrimSpace(rawURL)) + if err != nil { + return false + } + host := strings.ToLower(parsed.Hostname()) + for _, blocked := range nonOSINTHosts { + if host == blocked || strings.HasSuffix(host, "."+blocked) { + return true + } + } + return false +} diff --git a/internal/collector/run/run.go b/internal/collector/run/run.go index 11ee0a6..8818f08 100644 --- a/internal/collector/run/run.go +++ b/internal/collector/run/run.go @@ -168,6 +168,18 @@ func (r Runner) runOnce(ctx context.Context, cfg config.Config) error { if err != nil { return err } + // Purge stale alerts from sources that no longer exist or were rejected. + // Include source IDs from both the registry and the current fetch batch + // (covers synthetic alerts like the Interpol hub static entry). + activeSourceIDs := map[string]struct{}{} + for _, s := range sources { + activeSourceIDs[s.Source.SourceID] = struct{}{} + } + for _, a := range alerts { + activeSourceIDs[a.SourceID] = struct{}{} + } + previous = purgeOrphanAlerts(previous, activeSourceIDs) + accumulateSources := map[string]bool{} for _, s := range sources { if s.Accumulate { @@ -189,6 +201,19 @@ func (r Runner) runOnce(ctx context.Context, cfg config.Config) error { return err } +// purgeOrphanAlerts removes alerts whose source_id is no longer in the +// active registry. This cleans up zombie alerts from rejected or removed +// sources that would otherwise persist in the state file indefinitely. +func purgeOrphanAlerts(alerts []model.Alert, activeSourceIDs map[string]struct{}) []model.Alert { + out := make([]model.Alert, 0, len(alerts)) + for _, a := range alerts { + if _, ok := activeSourceIDs[a.SourceID]; ok { + out = append(out, a) + } + } + return out +} + func (r Runner) fetchSource(ctx context.Context, fetcher fetch.Fetcher, browser *fetch.BrowserClient, nctx normalize.Context, source model.RegistrySource, categoryDictionary *dictionary.Store, cursors state.Cursors) ([]model.Alert, error) { switch source.Type { case "rss": diff --git a/registry/source_registry.json b/registry/source_registry.json index 565c2ed..ace3923 100644 --- a/registry/source_registry.json +++ b/registry/source_registry.json @@ -5439,6 +5439,25 @@ "lat": 50.85, "lng": 4.35 }, + { + "type": "rss", + "promotion_status": "rejected", + "rejection_reason": "World Bank education content, not an intelligence source", + "source": { + "source_id": "worldbank-education-digital", + "authority_name": "World Bank Education Digital", + "country": "United States", + "country_code": "US", + "region": "International", + "authority_type": "regulatory", + "base_url": "https://www.worldbank.org" + }, + "feed_url": "https://www.worldbank.org/en/topic/edutech/rss.xml", + "category": "education_digital_capacity", + "region_tag": "INT", + "lat": 38.90, + "lng": -77.04 + }, { "type": "rss", "source": { From eaff169c594ec700e7b30a7dea60f451e6c0b010 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Tue, 17 Mar 2026 09:48:54 +0100 Subject: [PATCH 50/58] fix: update terminology from "feeds" to "streams" for consistency --- src/App.tsx | 4 ++-- src/components/FeedDirectory.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index b3047af..8ab53c5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -301,10 +301,10 @@ export default function App() { {selectedSourceIds.length > 0 - ? `Scoped to ${selectedSourceIds.length} feeds` + ? `Scoped to ${selectedSourceIds.length} streams` : categoryFilter !== "all" ? `Scoped to ${categoryFilter}` - : "All live feeds"} + : "All live streams"} {" // "} Build your intelligence pipeline — Contact us diff --git a/src/components/FeedDirectory.tsx b/src/components/FeedDirectory.tsx index 9c42695..cbe50c5 100644 --- a/src/components/FeedDirectory.tsx +++ b/src/components/FeedDirectory.tsx @@ -227,7 +227,7 @@ export function FeedDirectory({ {zoneSummary.feeds}

-
Feeds
+
Streams
From ba90beffc0f896f2bab7e71f906cd4acbad19e19 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Tue, 17 Mar 2026 09:54:11 +0100 Subject: [PATCH 51/58] Reject tasking noise --- internal/collector/discover/hygiene.go | 2 + internal/collector/parse/html.go | 4 ++ internal/collector/parse/html_test.go | 15 ++++++++ internal/sourcedb/db_test.go | 51 +++++++++++++++++++++++++ registry/source_registry.json | 38 ++++++++++++++++++ registry/sources.seed.db | Bin 3350528 -> 3350528 bytes 6 files changed, 110 insertions(+) diff --git a/internal/collector/discover/hygiene.go b/internal/collector/discover/hygiene.go index 2406d09..016c07e 100644 --- a/internal/collector/discover/hygiene.go +++ b/internal/collector/discover/hygiene.go @@ -48,6 +48,7 @@ var nonOSINTTerms = []string{ "zoo", "aquarium", "botanical", "lottery", "casino", "gambling", "dating", "matrimon", + "openstreetmap", "missing maps", "mapathon", "tasking manager", } // nonOSINTHosts rejects entire domains that are never OSINT-relevant. @@ -62,6 +63,7 @@ var nonOSINTHosts = []string{ "spotify.com", "netflix.com", "stackoverflow.com", "github.com", "schoolnet.eu", "european-schoolnet", + "openstreetmap.org", "hotosm.org", "missingmaps.org", } func passesDiscoveryHygiene(name string, website string, authorityType string) bool { diff --git a/internal/collector/parse/html.go b/internal/collector/parse/html.go index 86b207c..7457633 100644 --- a/internal/collector/parse/html.go +++ b/internal/collector/parse/html.go @@ -25,10 +25,14 @@ var junkTitles = []string{ "next", "previous", "page", "skip to content", "accept", "decline", "configuración de cookies", "mozilla firefox", "google chrome", "microsoft edge", + "reset filters", } func isJunkTitle(title string) bool { lower := strings.ToLower(title) + if strings.Contains(lower, "${") || strings.Contains(lower, "{{") { + return true + } for _, junk := range junkTitles { if lower == junk || strings.TrimSpace(lower) == junk { return true diff --git a/internal/collector/parse/html_test.go b/internal/collector/parse/html_test.go index 97984ad..ec51d68 100644 --- a/internal/collector/parse/html_test.go +++ b/internal/collector/parse/html_test.go @@ -15,3 +15,18 @@ func TestParseHTMLAnchors(t *testing.T) { t.Fatalf("unexpected link %q", items[0].Link) } } + +func TestParseHTMLAnchorsSkipsTemplateAndFilterNoise(t *testing.T) { + body := ` +${item.title} ${item.url} +Reset Filters +Disaster Response in Sudan +` + items := ParseHTMLAnchors(body, "https://agency.example.org/news") + if len(items) != 1 { + t.Fatalf("expected 1 item after filtering noise, got %d", len(items)) + } + if items[0].Title != "Disaster Response in Sudan" { + t.Fatalf("unexpected title %q", items[0].Title) + } +} diff --git a/internal/sourcedb/db_test.go b/internal/sourcedb/db_test.go index 9477d32..cc8a1da 100644 --- a/internal/sourcedb/db_test.go +++ b/internal/sourcedb/db_test.go @@ -286,6 +286,57 @@ func TestMergeRegistryAddsCuratedSeedWithoutReplacingExistingSources(t *testing. } } +func TestMergeRegistryRejectsExistingSource(t *testing.T) { + dir := t.TempDir() + baseRegistryPath := filepath.Join(dir, "base.json") + seedRegistryPath := filepath.Join(dir, "seed.json") + dbPath := filepath.Join(dir, "sources.db") + + base := `[ + {"type":"html-list","feed_url":"https://www.hotosm.org/projects/","category":"humanitarian_tasking","source":{"source_id":"hot-tasking","authority_name":"Humanitarian OpenStreetMap Team","country":"International","country_code":"INT","region":"International","authority_type":"public_safety_program","base_url":"https://www.hotosm.org"}} + ]` + seed := `[ + {"type":"html-list","feed_url":"https://www.hotosm.org/projects/","category":"humanitarian_tasking","promotion_status":"rejected","rejection_reason":"JS-rendered navigation page, not a stable incident/tasking feed","source":{"source_id":"hot-tasking","authority_name":"Humanitarian OpenStreetMap Team","country":"International","country_code":"INT","region":"International","authority_type":"public_safety_program","base_url":"https://www.hotosm.org"}} + ]` + if err := os.WriteFile(baseRegistryPath, []byte(base), 0o644); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(seedRegistryPath, []byte(seed), 0o644); err != nil { + t.Fatal(err) + } + + db, err := Open(dbPath) + if err != nil { + t.Fatal(err) + } + defer db.Close() + if err := db.ImportRegistry(context.Background(), baseRegistryPath); err != nil { + t.Fatal(err) + } + if err := db.MergeRegistry(context.Background(), seedRegistryPath); err != nil { + t.Fatal(err) + } + + sources, err := db.LoadActiveSources(context.Background()) + if err != nil { + t.Fatal(err) + } + if len(sources) != 0 { + t.Fatalf("expected rejected source to be removed from active load, got %d", len(sources)) + } + + var promotionStatus, rejectionReason string + if err := db.sql.QueryRowContext(context.Background(), `SELECT promotion_status, rejection_reason FROM sources WHERE id = 'hot-tasking'`).Scan(&promotionStatus, &rejectionReason); err != nil { + t.Fatal(err) + } + if promotionStatus != "rejected" { + t.Fatalf("expected promotion_status rejected, got %q", promotionStatus) + } + if rejectionReason == "" { + t.Fatal("expected rejection_reason to be persisted") + } +} + func TestSaveAndLoadAlertsReplacesMaterializedStateWithoutDuplicates(t *testing.T) { dir := t.TempDir() dbPath := filepath.Join(dir, "sources.db") diff --git a/registry/source_registry.json b/registry/source_registry.json index ace3923..64cf4d5 100644 --- a/registry/source_registry.json +++ b/registry/source_registry.json @@ -3081,6 +3081,44 @@ "lat": 40.75, "lng": -73.97 }, + { + "type": "html-list", + "promotion_status": "rejected", + "rejection_reason": "JS-rendered navigation page, not a stable incident/tasking feed", + "source": { + "source_id": "hot-tasking", + "authority_name": "Humanitarian OpenStreetMap Team", + "country": "International", + "country_code": "INT", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://www.hotosm.org" + }, + "feed_url": "https://www.hotosm.org/projects/", + "category": "humanitarian_tasking", + "region_tag": "INT", + "lat": 40.71, + "lng": -74.01 + }, + { + "type": "html-list", + "promotion_status": "rejected", + "rejection_reason": "Navigation/blog content about mapping events, not operational tasking intelligence", + "source": { + "source_id": "missing-maps-tasking", + "authority_name": "Missing Maps", + "country": "International", + "country_code": "INT", + "region": "International", + "authority_type": "public_safety_program", + "base_url": "https://www.missingmaps.org" + }, + "feed_url": "https://www.missingmaps.org/", + "category": "humanitarian_tasking", + "region_tag": "INT", + "lat": 51.51, + "lng": -0.13 + }, { "type": "rss", "promotion_status": "rejected", diff --git a/registry/sources.seed.db b/registry/sources.seed.db index 88cb259504e5c790b699282c29884d666e134620..95b00e7d1eae165ea568d2ad2c9736816debea1f 100644 GIT binary patch delta 128310 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

;rYg*#L^ecFm);WKvf8P-+ck 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 b; Date: Tue, 17 Mar 2026 10:04:34 +0100 Subject: [PATCH 52/58] Fix feed transport and filters --- internal/collector/discover/discover_test.go | 15 ++++++++ internal/collector/discover/gap.go | 9 +++-- internal/collector/discover/hygiene.go | 32 +++++++++++++++- internal/collector/discover/search_llm.go | 4 ++ internal/collector/fetch/stealth.go | 27 +++++++++---- internal/collector/run/run.go | 40 +++++++++++++++++--- internal/collector/run/run_test.go | 14 +++++++ 7 files changed, 124 insertions(+), 17 deletions(-) diff --git a/internal/collector/discover/discover_test.go b/internal/collector/discover/discover_test.go index 981ae24..d50a049 100644 --- a/internal/collector/discover/discover_test.go +++ b/internal/collector/discover/discover_test.go @@ -88,6 +88,21 @@ func TestDiscoveryHygieneRejectsLocalPolice(t *testing.T) { } } +func TestDiscoveryHygieneDoesNotTreatTransportAsSport(t *testing.T) { + if !passesDiscoveryHygiene("Ministry of Transport", "https://transport.gov.example", "national_security") { + t.Fatal("expected transport ministry to avoid sport false-positive") + } +} + +func TestSearchTopicLabelIncludesNewCategories(t *testing.T) { + if got := searchTopicLabel("maritime_security", "national_security"); !strings.Contains(got, "maritime security") { + t.Fatalf("expected maritime topic label, got %q", got) + } + if got := searchTopicLabel("legislative", "regulatory"); !strings.Contains(got, "sanctions") { + t.Fatalf("expected legislative topic label, got %q", got) + } +} + func TestLoadCandidateQueueAndDeadLetterSkip(t *testing.T) { dir := t.TempDir() candidatePath := filepath.Join(dir, "candidates.json") diff --git a/internal/collector/discover/gap.go b/internal/collector/discover/gap.go index ea0231b..a27172f 100644 --- a/internal/collector/discover/gap.go +++ b/internal/collector/discover/gap.go @@ -22,6 +22,9 @@ type gapTarget struct { var coreCategories = []string{ "cyber_advisory", "public_appeal", + "legislative", + "conflict_monitoring", + "maritime_security", } // expandedCategories adds intel, travel, and fraud for countries where these @@ -29,12 +32,12 @@ var coreCategories = []string{ var expandedCategories = []string{ "cyber_advisory", "public_appeal", - "travel_warning", - "intelligence_report", - "fraud_alert", "legislative", "conflict_monitoring", "maritime_security", + "travel_warning", + "intelligence_report", + "fraud_alert", } // targetCountries lists all countries the system should cover with at least diff --git a/internal/collector/discover/hygiene.go b/internal/collector/discover/hygiene.go index 016c07e..3eec490 100644 --- a/internal/collector/discover/hygiene.go +++ b/internal/collector/discover/hygiene.go @@ -6,6 +6,7 @@ package discover import ( "net/url" "strings" + "unicode" ) var localEntityTerms = []string{ @@ -78,7 +79,7 @@ func passesDiscoveryHygiene(name string, website string, authorityType string) b } } for _, term := range nonOSINTTerms { - if strings.Contains(name, term) { + if containsTerm(name, term) { return false } } @@ -125,3 +126,32 @@ func hostIsNonOSINT(rawURL string) bool { } return false } + +func containsTerm(text string, term string) bool { + text = strings.ToLower(strings.TrimSpace(text)) + term = strings.ToLower(strings.TrimSpace(term)) + if text == "" || term == "" { + return false + } + offset := 0 + for { + idx := strings.Index(text[offset:], term) + if idx < 0 { + return false + } + start := offset + idx + end := start + len(term) + if isBoundary(text, start-1) && isBoundary(text, end) { + return true + } + offset = start + 1 + } +} + +func isBoundary(text string, idx int) bool { + if idx < 0 || idx >= len(text) { + return true + } + r := rune(text[idx]) + return !unicode.IsLetter(r) && !unicode.IsDigit(r) +} diff --git a/internal/collector/discover/search_llm.go b/internal/collector/discover/search_llm.go index b140840..e7c3c77 100644 --- a/internal/collector/discover/search_llm.go +++ b/internal/collector/discover/search_llm.go @@ -180,6 +180,10 @@ func searchTopicLabel(category string, authorityType string) string { return "strategic intelligence assessments and geopolitical analysis" case "conflict_monitoring": return "armed conflict tracking, ceasefire monitoring, and peace processes" + case "maritime_security": + return "maritime security, piracy, shipping threats, coast guard activity, and naval incidents" + case "legislative": + return "sanctions, defense policy, foreign affairs, security legislation, and parliamentary security debates" case "humanitarian_security", "humanitarian_tasking": return "humanitarian operations, aid worker security, and crisis coordination" case "health_emergency", "disease_outbreak": diff --git a/internal/collector/fetch/stealth.go b/internal/collector/fetch/stealth.go index bb42fd5..7d6a0c7 100644 --- a/internal/collector/fetch/stealth.go +++ b/internal/collector/fetch/stealth.go @@ -34,7 +34,7 @@ import ( // disables Go's automatic gzip handling). func newStealthTransport(dialer *net.Dialer) http.RoundTripper { dt := &dualProtoTransport{ - dialer: dialer, + dialer: dialer, protoByHost: make(map[string]string), } @@ -64,7 +64,7 @@ type dualProtoTransport struct { h2 *http2.Transport mu sync.Mutex - protoByHost map[string]string // hostname -> "h2" | "h1" + protoByHost map[string]string // scheme://hostname -> "h2" | "h1" } func (dt *dualProtoTransport) dialTLS(ctx context.Context, network, addr string) (net.Conn, error) { @@ -91,19 +91,19 @@ func (dt *dualProtoTransport) dialTLS(ctx context.Context, network, addr string) proto := tlsConn.ConnectionState().NegotiatedProtocol dt.mu.Lock() if proto == "h2" { - dt.protoByHost[host] = "h2" + dt.protoByHost["https://"+host] = "h2" } else { - dt.protoByHost[host] = "h1" + dt.protoByHost["https://"+host] = "h1" } dt.mu.Unlock() return tlsConn, nil } -func (dt *dualProtoTransport) getProto(host string) string { +func (dt *dualProtoTransport) getProto(scheme string, host string) string { dt.mu.Lock() defer dt.mu.Unlock() - return dt.protoByHost[host] + return dt.protoByHost[scheme+"://"+host] } // stealthRoundTripper routes requests to the appropriate protocol @@ -113,8 +113,19 @@ type stealthRoundTripper struct { } func (s *stealthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + if req.URL.Scheme == "http" { + res, err := s.dual.h1.RoundTrip(req) + if err != nil { + return nil, err + } + if derr := decompressBody(res); derr != nil { + res.Body = io.NopCloser(bufio.NewReader(res.Body)) + } + return res, nil + } + host := req.URL.Hostname() - proto := s.dual.getProto(host) + proto := s.dual.getProto(req.URL.Scheme, host) var res *http.Response var err error @@ -131,7 +142,7 @@ func (s *stealthRoundTripper) RoundTrip(req *http.Request) (*http.Response, erro // dialTLS callback caches the negotiated proto regardless, so we // can detect this and retry with the h2 transport. res, err = s.dual.h1.RoundTrip(req) - if err != nil && s.dual.getProto(host) == "h2" { + if err != nil && s.dual.getProto(req.URL.Scheme, host) == "h2" { res, err = s.dual.h2.RoundTrip(req) } } diff --git a/internal/collector/run/run.go b/internal/collector/run/run.go index 8818f08..f029439 100644 --- a/internal/collector/run/run.go +++ b/internal/collector/run/run.go @@ -250,6 +250,7 @@ func (r Runner) fetchRSS(ctx context.Context, fetcher fetch.Fetcher, nctx normal fmt.Fprintf(r.stderr, "WARN %s: translate batch failed: %v\n", source.Source.AuthorityName, err) } } + items = filterFeedKeywords(items, source.IncludeKeywords, source.ExcludeKeywords) limit := perSourceLimit(nctx.Config, source) if len(items) > limit { items = items[:limit] @@ -364,11 +365,11 @@ func (r Runner) fetchInterpol(ctx context.Context, fetcher fetch.Fetcher, browse // Interpol's API sits behind Akamai WAF and requires XHR-style headers // with Referer/Origin pointing to the Interpol website. interpolHeaders := map[string]string{ - "Referer": "https://www.interpol.int/How-we-work/Notices/View-Notices", - "Origin": "https://www.interpol.int", - "Sec-Fetch-Dest": "empty", - "Sec-Fetch-Mode": "cors", - "Sec-Fetch-Site": "same-site", + "Referer": "https://www.interpol.int/How-we-work/Notices/View-Notices", + "Origin": "https://www.interpol.int", + "Sec-Fetch-Dest": "empty", + "Sec-Fetch-Mode": "cors", + "Sec-Fetch-Site": "same-site", "X-Requested-With": "XMLHttpRequest", } @@ -719,6 +720,35 @@ func filterKeywords(items []parse.FeedItem, include []string, exclude []string) return out } +func filterFeedKeywords(items []parse.FeedItem, include []string, exclude []string) []parse.FeedItem { + include = normalizeKeywords(include) + exclude = normalizeKeywords(exclude) + out := []parse.FeedItem{} + for _, item := range items { + includeHay := strings.ToLower(strings.Join([]string{ + item.Title, + item.Summary, + item.Author, + strings.Join(item.Tags, " "), + }, " ")) + excludeHay := strings.ToLower(strings.Join([]string{ + item.Title, + item.Summary, + item.Author, + strings.Join(item.Tags, " "), + item.Link, + }, " ")) + if len(include) > 0 && !containsKeyword(includeHay, include) { + continue + } + if len(exclude) > 0 && containsKeyword(excludeHay, exclude) { + continue + } + out = append(out, item) + } + return out +} + func normalizeKeywords(values []string) []string { out := make([]string, 0, len(values)) for _, value := range values { diff --git a/internal/collector/run/run_test.go b/internal/collector/run/run_test.go index dff2a9b..9d0bf36 100644 --- a/internal/collector/run/run_test.go +++ b/internal/collector/run/run_test.go @@ -219,6 +219,20 @@ func TestFilterCategoryItemsMatchesCatalanMissingPersonPage(t *testing.T) { } } +func TestFilterFeedKeywordsAppliesToRSSContent(t *testing.T) { + items := []parse.FeedItem{ + {Title: "Budget debate", Summary: "Parliament procedure only", Link: "https://example.test/a"}, + {Title: "Parliament update", Summary: "New sanctions package announced", Link: "https://example.test/b"}, + } + filtered := filterFeedKeywords(items, []string{"sanction"}, nil) + if len(filtered) != 1 { + t.Fatalf("expected 1 retained RSS item, got %d", len(filtered)) + } + if filtered[0].Link != "https://example.test/b" { + t.Fatalf("unexpected retained RSS item: %#v", filtered[0]) + } +} + func TestRunnerRunOnceUsesSQLiteAlertStateWithoutDuplicatingAlerts(t *testing.T) { dir := t.TempDir() registryPath := filepath.Join(dir, "sources.db") From 18359108c42cc7189dc8addd7dead10a40cf09dc Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Tue, 17 Mar 2026 10:08:54 +0100 Subject: [PATCH 53/58] Harden vetting and fetch fallback --- internal/collector/fetch/client_test.go | 39 ++++++++++++++++++ internal/collector/fetch/stealth.go | 37 +++++++++++++++-- internal/collector/vet/source.go | 53 ++++++++++++++++++++----- internal/collector/vet/source_test.go | 14 +++++++ 4 files changed, 129 insertions(+), 14 deletions(-) diff --git a/internal/collector/fetch/client_test.go b/internal/collector/fetch/client_test.go index c92ced5..865231a 100644 --- a/internal/collector/fetch/client_test.go +++ b/internal/collector/fetch/client_test.go @@ -113,8 +113,47 @@ func TestDecompressBodyIdentity(t *testing.T) { } } +func TestStealthRoundTripperFallsBackToHTTP11AfterHTTP2PeerError(t *testing.T) { + rt := &stealthRoundTripper{ + dual: &dualProtoTransport{ + protoByHost: map[string]string{"https://collector.test": "h2"}, + roundTripH2: func(req *http.Request) (*http.Response, error) { + return nil, roundTripError("stream error: stream ID 3; INTERNAL_ERROR; received from peer") + }, + roundTripH1: func(req *http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: 200, + Body: io.NopCloser(strings.NewReader("ok")), + Header: make(http.Header), + }, nil + }, + }, + } + + req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "https://collector.test/feed", nil) + if err != nil { + t.Fatal(err) + } + res, err := rt.RoundTrip(req) + if err != nil { + t.Fatal(err) + } + defer res.Body.Close() + body, err := io.ReadAll(res.Body) + if err != nil { + t.Fatal(err) + } + if string(body) != "ok" { + t.Fatalf("unexpected body %q", string(body)) + } +} + type roundTripFunc func(*http.Request) (*http.Response, error) func (fn roundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) { return fn(req) } + +type roundTripError string + +func (e roundTripError) Error() string { return string(e) } diff --git a/internal/collector/fetch/stealth.go b/internal/collector/fetch/stealth.go index 7d6a0c7..88c1209 100644 --- a/internal/collector/fetch/stealth.go +++ b/internal/collector/fetch/stealth.go @@ -65,6 +65,8 @@ type dualProtoTransport struct { mu sync.Mutex protoByHost map[string]string // scheme://hostname -> "h2" | "h1" + roundTripH1 func(*http.Request) (*http.Response, error) + roundTripH2 func(*http.Request) (*http.Response, error) } func (dt *dualProtoTransport) dialTLS(ctx context.Context, network, addr string) (net.Conn, error) { @@ -132,18 +134,21 @@ func (s *stealthRoundTripper) RoundTrip(req *http.Request) (*http.Response, erro switch proto { case "h2": - res, err = s.dual.h2.RoundTrip(req) + res, err = s.dual.doRoundTripH2(req) + if err != nil && shouldRetryH2AsH1(err) { + res, err = s.dual.doRoundTripH1(req) + } case "h1": - res, err = s.dual.h1.RoundTrip(req) + res, err = s.dual.doRoundTripH1(req) default: // Unknown host — try h1 first. If the server negotiates h2 via // ALPN, the h1 transport will fail with "malformed HTTP response" // because it tries HTTP/1.1 framing on an h2 connection. The // dialTLS callback caches the negotiated proto regardless, so we // can detect this and retry with the h2 transport. - res, err = s.dual.h1.RoundTrip(req) + res, err = s.dual.doRoundTripH1(req) if err != nil && s.dual.getProto(req.URL.Scheme, host) == "h2" { - res, err = s.dual.h2.RoundTrip(req) + res, err = s.dual.doRoundTripH2(req) } } @@ -157,6 +162,30 @@ func (s *stealthRoundTripper) RoundTrip(req *http.Request) (*http.Response, erro return res, nil } +func shouldRetryH2AsH1(err error) bool { + if err == nil { + return false + } + msg := strings.ToLower(err.Error()) + return strings.Contains(msg, "stream error") || + strings.Contains(msg, "internal_error") || + strings.Contains(msg, "received from peer") +} + +func (dt *dualProtoTransport) doRoundTripH1(req *http.Request) (*http.Response, error) { + if dt.roundTripH1 != nil { + return dt.roundTripH1(req) + } + return dt.h1.RoundTrip(req) +} + +func (dt *dualProtoTransport) doRoundTripH2(req *http.Request) (*http.Response, error) { + if dt.roundTripH2 != nil { + return dt.roundTripH2(req) + } + return dt.h2.RoundTrip(req) +} + // decompressBody wraps the response body reader to handle Content-Encoding. func decompressBody(res *http.Response) error { ce := strings.ToLower(strings.TrimSpace(res.Header.Get("Content-Encoding"))) diff --git a/internal/collector/vet/source.go b/internal/collector/vet/source.go index 61a63df..4f33d5a 100644 --- a/internal/collector/vet/source.go +++ b/internal/collector/vet/source.go @@ -8,6 +8,7 @@ import ( "encoding/json" "fmt" "regexp" + "strconv" "strings" "github.com/scalytics/euosint/internal/collector/config" @@ -34,14 +35,46 @@ type Input struct { } type Verdict struct { - Approve bool `json:"approve"` - PromotionStatus string `json:"promotion_status"` - Category string `json:"category,omitempty"` - Level string `json:"level"` - MissionTags []string `json:"mission_tags"` - SourceQuality float64 `json:"source_quality"` - OperationalRelevance float64 `json:"operational_relevance"` - Reason string `json:"reason"` + Approve bool `json:"approve"` + PromotionStatus string `json:"promotion_status"` + Category string `json:"category,omitempty"` + Level string `json:"level"` + MissionTags []string `json:"mission_tags"` + SourceQuality flexFloat `json:"source_quality"` + OperationalRelevance flexFloat `json:"operational_relevance"` + Reason string `json:"reason"` +} + +type flexFloat float64 + +func (f *flexFloat) UnmarshalJSON(data []byte) error { + raw := strings.TrimSpace(string(data)) + if raw == "" || raw == "null" { + *f = 0 + return nil + } + + var num float64 + if err := json.Unmarshal(data, &num); err == nil { + *f = flexFloat(num) + return nil + } + + var asString string + if err := json.Unmarshal(data, &asString); err != nil { + return err + } + asString = strings.TrimSpace(asString) + if asString == "" { + *f = 0 + return nil + } + num, err := strconv.ParseFloat(asString, 64) + if err != nil { + return err + } + *f = flexFloat(num) + return nil } type Vetter struct { @@ -179,8 +212,8 @@ func (v *Verdict) normalize() { default: v.Level = "national" } - v.SourceQuality = clamp01(v.SourceQuality) - v.OperationalRelevance = clamp01(v.OperationalRelevance) + v.SourceQuality = flexFloat(clamp01(float64(v.SourceQuality))) + v.OperationalRelevance = flexFloat(clamp01(float64(v.OperationalRelevance))) if !v.Approve { v.PromotionStatus = "rejected" } diff --git a/internal/collector/vet/source_test.go b/internal/collector/vet/source_test.go index fe8688d..72d4b73 100644 --- a/internal/collector/vet/source_test.go +++ b/internal/collector/vet/source_test.go @@ -20,6 +20,20 @@ func TestDecodeVerdictExtractsJSONBlock(t *testing.T) { } } +func TestDecodeVerdictAcceptsNumericStrings(t *testing.T) { + verdict, err := decodeVerdict(`{"approve":true,"promotion_status":"active","level":"national","source_quality":"0.9","operational_relevance":"0.8","mission_tags":["organized_crime"],"reason":"high signal"}`) + if err != nil { + t.Fatal(err) + } + verdict.normalize() + if float64(verdict.SourceQuality) != 0.9 { + t.Fatalf("expected source_quality 0.9, got %v", verdict.SourceQuality) + } + if float64(verdict.OperationalRelevance) != 0.8 { + t.Fatalf("expected operational_relevance 0.8, got %v", verdict.OperationalRelevance) + } +} + func TestDeterministicRejectsLocalAndMissingSamples(t *testing.T) { if _, reject := deterministicReject(Input{AuthorityName: "City of Valletta Police Department", Samples: []Sample{{Title: "x"}}}); !reject { t.Fatal("expected local police deterministic reject") From 77395127698f22051142d87a7d37dd08263d0ee7 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Tue, 17 Mar 2026 10:18:23 +0100 Subject: [PATCH 54/58] Tighten geocoding precision --- internal/collector/discover/discover.go | 4 +- internal/collector/normalize/normalize.go | 56 ++++++++++++++----- .../collector/normalize/normalize_test.go | 48 ++++++++++++++++ 3 files changed, 92 insertions(+), 16 deletions(-) diff --git a/internal/collector/discover/discover.go b/internal/collector/discover/discover.go index d147e73..47e9069 100644 --- a/internal/collector/discover/discover.go +++ b/internal/collector/discover/discover.go @@ -521,7 +521,7 @@ func vetAndPromote(ctx context.Context, cfg config.Config, client *fetch.Client, FeedURL: discovered.FeedURL, Category: firstNonEmpty(candidate.Category, discovered.Category), RegionTag: strings.ToUpper(strings.TrimSpace(candidate.CountryCode)), - SourceQuality: verdict.SourceQuality, + SourceQuality: float64(verdict.SourceQuality), PromotionStatus: verdict.PromotionStatus, Reporting: model.ReportingMetadata{}, Source: model.SourceMetadata{ @@ -535,7 +535,7 @@ func vetAndPromote(ctx context.Context, cfg config.Config, client *fetch.Client, Scope: verdict.Level, Level: verdict.Level, MissionTags: verdict.MissionTags, - OperationalRelevance: verdict.OperationalRelevance, + OperationalRelevance: float64(verdict.OperationalRelevance), LanguageCode: "", }, } diff --git a/internal/collector/normalize/normalize.go b/internal/collector/normalize/normalize.go index ba89b36..6030f35 100644 --- a/internal/collector/normalize/normalize.go +++ b/internal/collector/normalize/normalize.go @@ -145,7 +145,7 @@ func RSSItem(ctx Context, meta model.RegistrySource, item parse.FeedItem) *model if !isFresh(ctx.Config, publishedAt, ctx.Now) { return nil } - alert := baseAlert(ctx, meta, item.Title, item.Link, publishedAt) + alert := baseAlert(ctx, meta, item.Title, item.Link, item.Title+" "+item.Summary, publishedAt) triage := score(ctx.Config, alert, FeedContext{ Summary: item.Summary, Author: item.Author, @@ -163,7 +163,7 @@ func RSSItem(ctx Context, meta model.RegistrySource, item parse.FeedItem) *model } func HTMLItem(ctx Context, meta model.RegistrySource, item parse.FeedItem) *model.Alert { - alert := baseAlert(ctx, meta, item.Title, item.Link, ctx.Now) + alert := baseAlert(ctx, meta, item.Title, item.Link, item.Title+" "+item.Summary, ctx.Now) triage := score(ctx.Config, alert, FeedContext{ Summary: item.Summary, Tags: item.Tags, @@ -188,7 +188,7 @@ func KEVAlert(ctx Context, meta model.RegistrySource, cveID string, vulnName str if strings.TrimSpace(cveID) != "" { link = "https://nvd.nist.gov/vuln/detail/" + strings.TrimSpace(cveID) } - alert := baseAlert(ctx, meta, title, link, publishedAt) + alert := baseAlert(ctx, meta, title, link, title+" "+description, publishedAt) if hoursBetween(ctx.Now, publishedAt) <= 72 { alert.Severity = "critical" } else if hoursBetween(ctx.Now, publishedAt) <= 168 { @@ -210,7 +210,7 @@ func InterpolAlert(ctx Context, meta model.RegistrySource, noticeID string, titl if strings.TrimSpace(title) == "" { return nil } - alert := baseAlert(ctx, meta, title, firstNonEmpty(link, meta.Source.BaseURL), ctx.Now) + alert := baseAlert(ctx, meta, title, firstNonEmpty(link, meta.Source.BaseURL), title+" "+summary, ctx.Now) alert.Severity = "critical" if id := strings.TrimSpace(noticeID); id != "" { alert.AlertID = meta.Source.SourceID + ":" + id @@ -224,7 +224,7 @@ func InterpolAlert(ctx Context, meta model.RegistrySource, noticeID string, titl // Override lat/lng to the person's nationality country instead of // Interpol HQ (Lyon, France). if gLat, gLng, _, ok := geocodeCountryCode(code); ok { - alert.Lat, alert.Lng = jitter(gLat, gLng, meta.Source.SourceID+":"+link) + alert.Lat, alert.Lng = jitter(gLat, gLng, meta.Source.SourceID+":"+link, "capital") } } alert.Triage = score(ctx.Config, alert, FeedContext{ @@ -240,7 +240,7 @@ func FBIWantedAlert(ctx Context, meta model.RegistrySource, item parse.FeedItem) if publishedAt.IsZero() { publishedAt = ctx.Now } - alert := baseAlert(ctx, meta, item.Title, item.Link, publishedAt) + alert := baseAlert(ctx, meta, item.Title, item.Link, item.Title+" "+item.Summary, publishedAt) alert.Severity = "critical" triage := score(ctx.Config, alert, FeedContext{ Summary: item.Summary, @@ -259,7 +259,7 @@ func TravelWarningAlert(ctx Context, meta model.RegistrySource, item parse.FeedI if !isFresh(ctx.Config, publishedAt, ctx.Now) { return nil } - alert := baseAlert(ctx, meta, item.Title, item.Link, publishedAt) + alert := baseAlert(ctx, meta, item.Title, item.Link, item.Title+" "+item.Summary, publishedAt) alert.Severity = inferTravelWarningSeverity(item.Title, item.Summary, item.Tags) triage := score(ctx.Config, alert, FeedContext{ Summary: item.Summary, @@ -310,14 +310,19 @@ func StaticInterpolEntry(now time.Time) model.Alert { } } -func baseAlert(ctx Context, meta model.RegistrySource, title string, link string, publishedAt time.Time) model.Alert { +func baseAlert(ctx Context, meta model.RegistrySource, title string, link string, geoText string, publishedAt time.Time) model.Alert { title = strings.TrimSpace(title) + geoText = strings.TrimSpace(geoText) + if geoText == "" { + geoText = title + } // Fix broken NCMEC-style titles that start with ": Name (State)". if strings.HasPrefix(title, ": ") { title = "Missing" + title } baseLat, baseLng := meta.Lat, meta.Lng + geoSource := "registry" source := meta.Source // Use capital coords instead of geographic centroid for the source's @@ -325,6 +330,7 @@ func baseAlert(ctx Context, meta model.RegistrySource, title string, link string if source.CountryCode != "" && source.CountryCode != "INT" { if capital, ok := capitalCoords[source.CountryCode]; ok { baseLat, baseLng = capital[0], capital[1] + geoSource = "capital" } } @@ -335,8 +341,9 @@ func baseAlert(ctx Context, meta model.RegistrySource, title string, link string if meta.RegionTag == "INT" || meta.Source.CountryCode == "INT" { if ctx.Geocoder != nil { // Enhanced geocoding: city DB → Nominatim → country text. - if result := ctx.Geocoder.Resolve(context.Background(), title, ""); result.CountryCode != "" { + if result := ctx.Geocoder.Resolve(context.Background(), geoText, ""); result.CountryCode != "" { baseLat, baseLng = result.Lat, result.Lng + geoSource = result.Source geocoded = true if name := countryNameFromCode(result.CountryCode); name != "" { source.Country = name @@ -345,8 +352,9 @@ func baseAlert(ctx Context, meta model.RegistrySource, title string, link string } } if !geocoded { - if gLat, gLng, code, ok := geocodeText(title); ok { + if gLat, gLng, code, ok := geocodeText(geoText); ok { baseLat, baseLng = gLat, gLng + geoSource = "country-text" if name := countryNameFromCode(code); name != "" { source.Country = name source.CountryCode = code @@ -356,12 +364,14 @@ func baseAlert(ctx Context, meta model.RegistrySource, title string, link string } else if ctx.Geocoder != nil { // Non-international source: try city-level geocoding within the // source's country for better pin placement. - if result := ctx.Geocoder.Resolve(context.Background(), title, source.CountryCode); result.Source == "city-db" || result.Source == "nominatim" { + if result := ctx.Geocoder.Resolve(context.Background(), geoText, source.CountryCode); result.CountryCode != "" && + (result.Source == "city-db" || result.Source == "nominatim" || result.CountryCode == source.CountryCode) { baseLat, baseLng = result.Lat, result.Lng + geoSource = result.Source } } - lat, lng := jitter(baseLat, baseLng, meta.Source.SourceID+":"+link) + lat, lng := jitter(baseLat, baseLng, meta.Source.SourceID+":"+link, geoSource) return model.Alert{ AlertID: meta.Source.SourceID + "-" + hashID(link), SourceID: meta.Source.SourceID, @@ -689,10 +699,11 @@ func hashID(value string) string { return hex.EncodeToString(sum[:])[:12] } -func jitter(lat float64, lng float64, seed string) (float64, float64) { +func jitter(lat float64, lng float64, seed string, geoSource string) (float64, float64) { sum := sha1.Sum([]byte(seed)) angle := float64(sum[0])/255*math.Pi*2 + float64(sum[1])/255 - radius := 22 + float64(sum[2])/255*55 + minRadius, maxRadius := jitterRadiusKM(geoSource) + radius := minRadius + float64(sum[2])/255*(maxRadius-minRadius) dLat := (radius / 111.32) * math.Cos(angle) cosLat := math.Max(0.2, math.Cos((lat*math.Pi)/180)) dLng := (radius / (111.32 * cosLat)) * math.Sin(angle) @@ -707,6 +718,23 @@ func jitter(lat float64, lng float64, seed string) (float64, float64) { return round5(outLat), round5(outLng) } +func jitterRadiusKM(geoSource string) (float64, float64) { + switch geoSource { + case "city-db": + return 0.4, 1.6 + case "nominatim": + return 0.8, 2.5 + case "capital": + return 1.2, 4 + case "country-text": + return 4, 14 + case "registry": + return 2, 10 + default: + return 2, 10 + } +} + func extractDomain(raw string) string { u, err := url.Parse(raw) if err != nil { diff --git a/internal/collector/normalize/normalize_test.go b/internal/collector/normalize/normalize_test.go index 2e27b70..e8d0b24 100644 --- a/internal/collector/normalize/normalize_test.go +++ b/internal/collector/normalize/normalize_test.go @@ -122,3 +122,51 @@ func TestLocalCrimeDownranked(t *testing.T) { crossBorderAlert.Triage.RelevanceScore, localAlert.Triage.RelevanceScore) } } + +func TestJitterRadiusKMIsPrecisionAware(t *testing.T) { + cityMin, cityMax := jitterRadiusKM("city-db") + countryMin, countryMax := jitterRadiusKM("country-text") + if cityMax >= countryMin { + t.Fatalf("expected city jitter to be tighter than country jitter, got city %.1f-%.1f km vs country %.1f-%.1f km", cityMin, cityMax, countryMin, countryMax) + } + if cityMax > 2 { + t.Fatalf("expected city-db jitter to stay very tight, got max %.1f km", cityMax) + } +} + +func TestRSSItemUsesSummaryForCityPlacement(t *testing.T) { + cfg := config.Default() + ctx := Context{ + Config: cfg, + Now: time.Date(2026, 3, 17, 0, 0, 0, 0, time.UTC), + Geocoder: NewGeocoder(&mockCityLookup{cities: map[string]CityLookupResult{ + "Valletta|MT": {Name: "Valletta", CountryCode: "MT", Lat: 35.90, Lng: 14.51, Population: 6400}, + }}, nil), + } + meta := model.RegistrySource{ + Type: "rss", + Category: "public_safety", + Source: model.SourceMetadata{ + SourceID: "malta-civil", + AuthorityName: "Malta Civil Protection", + Country: "Malta", + CountryCode: "MT", + Region: "Europe", + AuthorityType: "public_safety_program", + BaseURL: "https://example.test", + }, + } + item := parse.FeedItem{ + Title: "Incident update", + Summary: "Emergency crews dispatched in Valletta harbour district", + Link: "https://example.test/incident", + Published: "2026-03-16T10:00:00Z", + } + alert := RSSItem(ctx, meta, item) + if alert == nil { + t.Fatal("expected alert") + } + if alert.Lat < 35.7 || alert.Lat > 36.1 || alert.Lng < 14.3 || alert.Lng > 14.7 { + t.Fatalf("expected alert to stay near Valletta, got (%f, %f)", alert.Lat, alert.Lng) + } +} From 178a2150588ec50cce0c036f7d763a536f4cdb98 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Tue, 17 Mar 2026 10:32:12 +0100 Subject: [PATCH 55/58] Improve install flow and clean bootstrap --- .env.example | 2 + Dockerfile.collector | 1 - README.md | 18 +- deploy/install.sh | 307 +++++++++++++++++++++++++++++++++ docker-compose.yml | 2 + docker/collector-entrypoint.sh | 18 +- docs/operations.md | 2 +- 7 files changed, 343 insertions(+), 7 deletions(-) create mode 100755 deploy/install.sh diff --git a/.env.example b/.env.example index 441ba6c..26b0034 100644 --- a/.env.example +++ b/.env.example @@ -4,6 +4,8 @@ EUOSINT_SITE_ADDRESS=:80 EUOSINT_HTTP_PORT=8080 EUOSINT_HTTPS_PORT=8443 +EUOSINT_WEB_IMAGE=ghcr.io/scalytics/euosint-web:latest +EUOSINT_COLLECTOR_IMAGE=ghcr.io/scalytics/euosint-collector:latest HTTP_TIMEOUT_MS=60000 BROWSER_ENABLED=true BROWSER_TIMEOUT_MS=60000 diff --git a/Dockerfile.collector b/Dockerfile.collector index 8ac19b7..ac9a1d8 100644 --- a/Dockerfile.collector +++ b/Dockerfile.collector @@ -30,7 +30,6 @@ WORKDIR /app COPY --from=build /out/euosint-collector /usr/local/bin/euosint-collector COPY --from=geonames /tmp/cities500.txt ./registry/cities500.txt COPY registry ./registry -COPY public ./public-defaults COPY docker/collector-entrypoint.sh /usr/local/bin/collector-entrypoint.sh RUN chmod +x /usr/local/bin/collector-entrypoint.sh diff --git a/README.md b/README.md index 2a486c4..ccc602d 100644 --- a/README.md +++ b/README.md @@ -30,10 +30,26 @@ make dev-restart make dev-logs ``` +## Remote Install (wget bootstrap) + +```bash +wget -qO- https://raw.githubusercontent.com/scalytics/EUOSINT/main/deploy/install.sh | bash +``` + +The installer will: +- verify Docker + Compose availability +- clone or update the repo on the host +- set GHCR runtime images (`ghcr.io/scalytics/euosint-web` + `ghcr.io/scalytics/euosint-collector`) +- prompt for install mode (`preserve` or `fresh` volume reset) +- prompt for domain (`EUOSINT_SITE_ADDRESS`) +- when domain mode is enabled, optionally check `ufw`/`firewalld` and validate local 80/443 availability +- prompt for key runtime flags (browser + LLM vetting settings) +- optionally run `docker compose pull` and start with `--no-build` + - The release pipeline now builds two images: a web image and a Go collector image. - The scheduled feed refresh workflow now runs the Go collector. - The web image now uses Caddy instead of nginx, with the collector output mounted into the web container at runtime. -- In Docker dev mode, the collector seeds the shared feed volume with the repository snapshots first, then replaces them with live output on the first successful run. +- In Docker dev mode, the collector initializes empty JSON outputs on a fresh volume and then writes live output on the first successful run. ## Run Locally Without Docker diff --git a/deploy/install.sh b/deploy/install.sh new file mode 100755 index 0000000..e1a2007 --- /dev/null +++ b/deploy/install.sh @@ -0,0 +1,307 @@ +#!/usr/bin/env bash +# EUOSINT remote installer +# Usage: +# wget -qO- https://raw.githubusercontent.com/scalytics/EUOSINT/main/deploy/install.sh | bash +# +# Optional environment overrides: +# REPO_URL=https://github.com/scalytics/EUOSINT.git +# REPO_REF=main +# INSTALL_DIR=/opt/euosint +# IMAGE_TAG=latest + +set -euo pipefail + +REPO_URL="${REPO_URL:-https://github.com/scalytics/EUOSINT.git}" +REPO_REF="${REPO_REF:-main}" +INSTALL_DIR="${INSTALL_DIR:-/opt/euosint}" +IMAGE_TAG="${IMAGE_TAG:-latest}" +INSTALL_MODE="${INSTALL_MODE:-preserve}" +TLS_MODE="false" + +info() { echo "[euosint-install] $*"; } +warn() { echo "[euosint-install][warn] $*" >&2; } +fatal() { echo "[euosint-install][error] $*" >&2; exit 1; } + +require_cmd() { + command -v "$1" >/dev/null 2>&1 || fatal "Missing required command: $1" +} + +prompt() { + local label="$1" + local default_value="${2:-}" + local value + if [[ -n "${default_value}" ]]; then + read -r -p "$label [$default_value]: " value + echo "${value:-$default_value}" + else + read -r -p "$label: " value + echo "$value" + fi +} + +prompt_yes_no() { + local label="$1" + local default_value="$2" + local value + while true; do + read -r -p "$label [$default_value]: " value + value="${value:-$default_value}" + value="$(echo "$value" | tr '[:upper:]' '[:lower:]')" + case "$value" in + y|yes) echo "yes"; return 0 ;; + n|no) echo "no"; return 0 ;; + *) echo "Please answer yes or no." ;; + esac + done +} + +prompt_install_mode() { + local value + while true; do + read -r -p "Install mode (preserve/fresh) [${INSTALL_MODE}]: " value + value="${value:-$INSTALL_MODE}" + value="$(echo "$value" | tr '[:upper:]' '[:lower:]')" + case "$value" in + preserve|fresh) echo "$value"; return 0 ;; + *) echo "Please answer 'preserve' or 'fresh'." ;; + esac + done +} + +ensure_docker() { + if ! command -v docker >/dev/null 2>&1; then + fatal "Docker is not installed. Install Docker Engine + Compose plugin first, then re-run." + fi + if ! docker info >/dev/null 2>&1; then + fatal "Docker daemon is not reachable. Start Docker and re-run." + fi + + if docker compose version >/dev/null 2>&1; then + COMPOSE_CMD="docker compose" + return 0 + fi + if command -v docker-compose >/dev/null 2>&1; then + COMPOSE_CMD="docker-compose" + return 0 + fi + fatal "Docker Compose is not available (need 'docker compose' plugin or 'docker-compose')." +} + +clone_or_update_repo() { + if [[ -d "$INSTALL_DIR/.git" ]]; then + info "Repository already exists in $INSTALL_DIR. Updating to $REPO_REF." + git -C "$INSTALL_DIR" fetch --tags origin + git -C "$INSTALL_DIR" checkout "$REPO_REF" + git -C "$INSTALL_DIR" pull --ff-only origin "$REPO_REF" || true + elif [[ -d "$INSTALL_DIR" && -n "$(ls -A "$INSTALL_DIR" 2>/dev/null || true)" ]]; then + fatal "Install directory exists and is not empty: $INSTALL_DIR" + else + info "Cloning $REPO_URL into $INSTALL_DIR." + git clone --depth 1 --branch "$REPO_REF" "$REPO_URL" "$INSTALL_DIR" + fi +} + +upsert_env() { + local file="$1" + local key="$2" + local value="$3" + if grep -qE "^${key}=" "$file"; then + sed -i.bak -E "s|^${key}=.*$|${key}=${value}|" "$file" + else + echo "${key}=${value}" >> "$file" + fi +} + +configure_env() { + local env_file="$INSTALL_DIR/.env" + local example_file="$INSTALL_DIR/.env.example" + + [[ -f "$example_file" ]] || fatal "Missing .env.example in repository." + + if [[ -f "$env_file" ]]; then + cp "$env_file" "$env_file.preinstall.$(date +%Y%m%d%H%M%S).bak" + info "Existing .env backed up." + else + cp "$example_file" "$env_file" + info "Created .env from .env.example." + fi + + local image_tag + image_tag="$(prompt "GHCR image tag to deploy" "$IMAGE_TAG")" + upsert_env "$env_file" "EUOSINT_WEB_IMAGE" "ghcr.io/scalytics/euosint-web:${image_tag}" + upsert_env "$env_file" "EUOSINT_COLLECTOR_IMAGE" "ghcr.io/scalytics/euosint-collector:${image_tag}" + info "Configured GHCR images with tag '${image_tag}'." + + local domain + domain="$(prompt "Domain for public access (blank for localhost dev mode)" "")" + + if [[ -n "$domain" ]]; then + TLS_MODE="true" + upsert_env "$env_file" "EUOSINT_SITE_ADDRESS" "$domain" + upsert_env "$env_file" "EUOSINT_HTTP_PORT" "80" + upsert_env "$env_file" "EUOSINT_HTTPS_PORT" "443" + info "Configured domain '$domain' with ports 80/443." + warn "Ensure DNS A/AAAA records point to this host and inbound 80/443 are open." + else + TLS_MODE="false" + upsert_env "$env_file" "EUOSINT_SITE_ADDRESS" ":80" + upsert_env "$env_file" "EUOSINT_HTTP_PORT" "8080" + upsert_env "$env_file" "EUOSINT_HTTPS_PORT" "8443" + info "Configured localhost mode on 8080/8443." + fi + + local browser_choice + browser_choice="$(prompt_yes_no "Enable browser-assisted fetches (higher accuracy, higher resource use)?" "yes")" + if [[ "$browser_choice" == "yes" ]]; then + upsert_env "$env_file" "BROWSER_ENABLED" "true" + else + upsert_env "$env_file" "BROWSER_ENABLED" "false" + fi + + local vetting_choice + vetting_choice="$(prompt_yes_no "Enable LLM source vetting?" "no")" + if [[ "$vetting_choice" == "yes" ]]; then + local provider base_url model api_key + provider="$(prompt "Vetting provider label (openai/xai/mistral/...)" "xai")" + base_url="$(prompt "Vetting base URL" "https://api.x.ai/v1")" + model="$(prompt "Vetting model" "grok-4-1-fast")" + api_key="$(prompt "Vetting API key (required)" "")" + [[ -n "$api_key" ]] || fatal "Vetting enabled but API key is empty." + + upsert_env "$env_file" "SOURCE_VETTING_ENABLED" "true" + upsert_env "$env_file" "SOURCE_VETTING_PROVIDER" "$provider" + upsert_env "$env_file" "SOURCE_VETTING_BASE_URL" "$base_url" + upsert_env "$env_file" "SOURCE_VETTING_MODEL" "$model" + upsert_env "$env_file" "SOURCE_VETTING_API_KEY" "$api_key" + else + upsert_env "$env_file" "SOURCE_VETTING_ENABLED" "false" + upsert_env "$env_file" "SOURCE_VETTING_API_KEY" "" + fi + + local alert_llm_choice + alert_llm_choice="$(prompt_yes_no "Enable LLM alert translation/classification?" "no")" + if [[ "$alert_llm_choice" == "yes" ]]; then + upsert_env "$env_file" "ALERT_LLM_ENABLED" "true" + else + upsert_env "$env_file" "ALERT_LLM_ENABLED" "false" + fi +} + +container_running_for_service() { + local service="$1" + local output + output="$(cd "$INSTALL_DIR" && $COMPOSE_CMD ps --status running --services 2>/dev/null || true)" + echo "$output" | grep -qx "$service" +} + +find_port_listener() { + local port="$1" + + if command -v lsof >/dev/null 2>&1; then + lsof -nP -iTCP:"$port" -sTCP:LISTEN 2>/dev/null | awk 'NR==2 {print $1 " (pid " $2 ") " $9; exit}' + return 0 + fi + + if command -v ss >/dev/null 2>&1; then + ss -ltnp 2>/dev/null | awk -v p=":$port" '$4 ~ p {print $0; exit}' + return 0 + fi + + return 1 +} + +validate_tls_ports() { + local listener + for port in 80 443; do + listener="$(find_port_listener "$port" || true)" + if [[ -n "$listener" ]]; then + fatal "Port ${port} is already in use (${listener}). Free it before TLS mode startup." + fi + done +} + +run_firewall_checks() { + if command -v ufw >/dev/null 2>&1; then + info "ufw detected. Current status:" + ufw status || true + elif command -v firewall-cmd >/dev/null 2>&1; then + info "firewalld detected. Listing public zone rules:" + firewall-cmd --zone=public --list-services || true + firewall-cmd --zone=public --list-ports || true + else + warn "No ufw/firewalld command found; skipping firewall inspection." + fi +} + +preflight_tls_checks() { + if [[ "$TLS_MODE" != "true" ]]; then + return 0 + fi + + info "TLS mode detected (domain set)." + local firewall_choice + firewall_choice="$(prompt_yes_no "Run firewall checks for 80/443 (ufw/firewalld)?" "yes")" + if [[ "$firewall_choice" == "yes" ]]; then + run_firewall_checks + fi + + if [[ "$INSTALL_MODE" == "preserve" ]] && container_running_for_service "euosint"; then + info "Existing euosint service is running; skipping strict local port-collision pre-check." + else + info "Validating that ports 80 and 443 are free..." + validate_tls_ports + fi +} + +start_stack() { + local start_choice + start_choice="$(prompt_yes_no "Start EUOSINT now with Docker Compose?" "yes")" + if [[ "$start_choice" != "yes" ]]; then + if [[ "$INSTALL_MODE" == "fresh" ]]; then + info "Installation complete. Start later with: cd $INSTALL_DIR && $COMPOSE_CMD down -v --remove-orphans && $COMPOSE_CMD pull && $COMPOSE_CMD up -d --no-build" + else + info "Installation complete. Start later with: cd $INSTALL_DIR && $COMPOSE_CMD pull && $COMPOSE_CMD up -d --no-build" + fi + return 0 + fi + + preflight_tls_checks + + if [[ "$INSTALL_MODE" == "fresh" ]]; then + warn "Fresh mode selected: stopping stack and deleting Compose volumes (feed-data/caddy-data/caddy-config)." + ( + cd "$INSTALL_DIR" + $COMPOSE_CMD down -v --remove-orphans || true + ) + else + info "Preserve mode selected: keeping existing Docker volumes/data." + fi + + info "Pulling latest GHCR images..." + ( + cd "$INSTALL_DIR" + $COMPOSE_CMD pull + ) + + info "Starting stack without local builds..." + ( + cd "$INSTALL_DIR" + $COMPOSE_CMD up -d --no-build + ) + + local http_port + http_port="$(grep -E '^EUOSINT_HTTP_PORT=' "$INSTALL_DIR/.env" | cut -d= -f2 || echo "8080")" + info "EUOSINT started. HTTP endpoint: http://$(hostname -f 2>/dev/null || hostname):${http_port}" +} + +main() { + require_cmd git + ensure_docker + INSTALL_MODE="$(prompt_install_mode)" + info "Selected install mode: ${INSTALL_MODE}" + clone_or_update_repo + configure_env + start_stack +} + +main "$@" diff --git a/docker-compose.yml b/docker-compose.yml index 842c4a3..a85daab 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,6 @@ services: collector: + image: "${EUOSINT_COLLECTOR_IMAGE:-ghcr.io/scalytics/euosint-collector:latest}" build: context: . dockerfile: Dockerfile.collector @@ -42,6 +43,7 @@ services: restart: unless-stopped euosint: + image: "${EUOSINT_WEB_IMAGE:-ghcr.io/scalytics/euosint-web:latest}" build: context: . dockerfile: Dockerfile diff --git a/docker/collector-entrypoint.sh b/docker/collector-entrypoint.sh index 59ac153..2447748 100644 --- a/docker/collector-entrypoint.sh +++ b/docker/collector-entrypoint.sh @@ -13,12 +13,22 @@ seed_if_missing() { fi } +init_json_if_missing() { + target_path="$1" + payload="$2" + if [ ! -f "$target_path" ]; then + printf '%s\n' "$payload" > "$target_path" + fi +} + mkdir -p /data -seed_if_missing /app/public-defaults/alerts.json /data/alerts.json -seed_if_missing /app/public-defaults/alerts-filtered.json /data/alerts-filtered.json -seed_if_missing /app/public-defaults/alerts-state.json /data/alerts-state.json -seed_if_missing /app/public-defaults/source-health.json /data/source-health.json +# Start fresh volumes with empty JSON documents to avoid serving stale +# baked snapshots from previous registry revisions. +init_json_if_missing /data/alerts.json '[]' +init_json_if_missing /data/alerts-filtered.json '[]' +init_json_if_missing /data/alerts-state.json '[]' +init_json_if_missing /data/source-health.json '{"generated_at":"","critical_source_prefixes":[],"fail_on_critical_source_gap":false,"total_sources":0,"sources_ok":0,"sources_error":0,"duplicate_audit":{"suppressed_variant_duplicates":0,"repeated_title_groups_in_active":0,"repeated_title_samples":[]},"sources":[]}' seed_if_missing /app/registry/source_candidates.json /data/source_candidates.json if [ ! -f /data/sources.db ]; then diff --git a/docs/operations.md b/docs/operations.md index a3425fe..e510d31 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -33,7 +33,7 @@ Default local behavior: - HTTP on `http://localhost:8080` - HTTPS listener mapped to `https://localhost:8443` but not used unless `EUOSINT_SITE_ADDRESS` is changed to a hostname that enables TLS -- The collector seeds the shared feed volume with bundled JSON snapshots if the volume is empty, so the UI has data immediately while the first live refresh runs +- The collector initializes empty JSON outputs on a fresh shared feed volume, then replaces them with live collector output on the first successful run ## Domain Setup For A VM From 33528f3a6373d1c28d830703b195e7c013b41c42 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Tue, 17 Mar 2026 10:43:27 +0100 Subject: [PATCH 56/58] Harden Docker builds and Chromium install --- .github/workflows/docker.yml | 20 +++++++++++++++++--- .github/workflows/release.yml | 21 ++++++++++++++++++--- Dockerfile.collector | 16 +++++++++++++++- docker-compose.yml | 2 +- 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index ef4e0ae..e2a2f48 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -56,7 +56,9 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Build image + - name: Build image (attempt 1) + id: build_image_1 + continue-on-error: true uses: docker/build-push-action@v6 with: context: . @@ -64,5 +66,17 @@ jobs: push: false load: false provenance: false - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=gha,scope=docker-${{ matrix.image.name }} + cache-to: type=gha,mode=max,scope=docker-${{ matrix.image.name }} + + - name: Build image (attempt 2 on transient failure) + if: steps.build_image_1.outcome == 'failure' + uses: docker/build-push-action@v6 + with: + context: . + file: ./${{ matrix.image.dockerfile }} + push: false + load: false + provenance: false + cache-from: type=gha,scope=docker-${{ matrix.image.name }} + cache-to: type=gha,mode=max,scope=docker-${{ matrix.image.name }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2224105..a165df7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -71,7 +71,9 @@ jobs: type=sha type=raw,value=latest - - name: Build and push image + - name: Build and push image (attempt 1) + id: build_push_1 + continue-on-error: true uses: docker/build-push-action@v6 with: context: . @@ -80,8 +82,21 @@ jobs: provenance: false tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=gha,scope=release-${{ matrix.image.name }} + cache-to: type=gha,mode=max,scope=release-${{ matrix.image.name }} + + - name: Build and push image (attempt 2 on transient failure) + if: steps.build_push_1.outcome == 'failure' + uses: docker/build-push-action@v6 + with: + context: . + file: ./${{ matrix.image.dockerfile }} + push: true + provenance: false + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha,scope=release-${{ matrix.image.name }} + cache-to: type=gha,mode=max,scope=release-${{ matrix.image.name }} - name: Publish GitHub release if: matrix.image.name == 'web' diff --git a/Dockerfile.collector b/Dockerfile.collector index ac9a1d8..2bf3d9f 100644 --- a/Dockerfile.collector +++ b/Dockerfile.collector @@ -22,7 +22,21 @@ RUN curl -sL https://download.geonames.org/export/dump/cities500.zip -o /tmp/cit FROM alpine:3.20 -RUN apk add --no-cache ca-certificates chromium +RUN set -eux; \ + apk add --no-cache ca-certificates; \ + i=0; \ + until [ "$i" -ge 3 ]; do \ + if apk add --no-cache chromium; then \ + break; \ + fi; \ + i=$((i + 1)); \ + if [ "$i" -ge 3 ]; then \ + echo "ERROR: failed to install chromium after 3 attempts" >&2; \ + exit 1; \ + fi; \ + echo "WARN: chromium install failed, retrying in 5s..." >&2; \ + sleep 5; \ + done ENV CHROME_PATH=/usr/bin/chromium-browser WORKDIR /app diff --git a/docker-compose.yml b/docker-compose.yml index a85daab..a598977 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -32,7 +32,7 @@ services: NOMINATIM_ENABLED: "1" DDG_SEARCH_ENABLED: "1" DDG_SEARCH_DELAY_MS: "8000" - BROWSER_ENABLED: "1" + BROWSER_ENABLED: "${BROWSER_ENABLED:-1}" INTERVAL_MS: "900000" MAX_PER_SOURCE: "40" MISSING_PERSON_RELEVANCE_THRESHOLD: "0" From bdfb64b4d994bd5b2bfe5c4689314ea7fda7bef5 Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Tue, 17 Mar 2026 10:58:46 +0100 Subject: [PATCH 57/58] Fix Header lint errors --- src/components/Header.tsx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 41fc19d..a6ecbb1 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -37,13 +37,6 @@ const REGIONS = [ "International", ]; -const _MENU_ITEMS: { key: MenuView; label: string }[] = [ - { key: "overview", label: "Overview" }, - { key: "feeds", label: "Feeds" }, - { key: "authorities", label: "Authorities" }, - { key: "health", label: "Source Health" }, -]; - const SEARCH_HISTORY_COOKIE = "euosint_search_history"; function readSearchHistory(): string[] { @@ -499,6 +492,8 @@ export function Header({ onMenuChange, alerts, }: Props) { + void activeMenu; + void onMenuChange; return (

From aa953a9952cbc973a7a2c7fe0ffaa2b960b38f7d Mon Sep 17 00:00:00 2001 From: 2pk03 Date: Tue, 17 Mar 2026 11:08:22 +0100 Subject: [PATCH 58/58] Run gofmt on collector and sourcedb files --- internal/collector/api/api_test.go | 42 +-- internal/collector/discover/humanitarian.go | 8 +- internal/collector/discover/report.go | 6 +- .../collector/discover/search_ddg_test.go | 4 +- internal/collector/normalize/geocode.go | 298 +++++++++--------- .../collector/normalize/geocode_capitals.go | 288 ++++++++--------- .../collector/normalize/geocode_nominatim.go | 1 - internal/collector/parse/fbi.go | 1 - internal/sourcedb/db.go | 10 +- 9 files changed, 328 insertions(+), 330 deletions(-) diff --git a/internal/collector/api/api_test.go b/internal/collector/api/api_test.go index f2eb891..11f663d 100644 --- a/internal/collector/api/api_test.go +++ b/internal/collector/api/api_test.go @@ -33,14 +33,14 @@ func seedAlerts(t *testing.T, db *sourcedb.DB) { t.Helper() alerts := []model.Alert{ { - AlertID: "a1", - SourceID: "europol", - Status: "active", - Title: "Europol dismantles major drug trafficking network", + AlertID: "a1", + SourceID: "europol", + Status: "active", + Title: "Europol dismantles major drug trafficking network", CanonicalURL: "https://europol.europa.eu/a1", - Category: "public_appeal", - Severity: "high", - RegionTag: "EU", + Category: "public_appeal", + Severity: "high", + RegionTag: "EU", Source: model.SourceMetadata{ SourceID: "europol", AuthorityName: "Europol", @@ -50,14 +50,14 @@ func seedAlerts(t *testing.T, db *sourcedb.DB) { }, }, { - AlertID: "a2", - SourceID: "fbi-wanted", - Status: "active", - Title: "FBI Most Wanted: Cyber fugitive identified", + AlertID: "a2", + SourceID: "fbi-wanted", + Status: "active", + Title: "FBI Most Wanted: Cyber fugitive identified", CanonicalURL: "https://fbi.gov/a2", - Category: "wanted_suspect", - Severity: "critical", - RegionTag: "US", + Category: "wanted_suspect", + Severity: "critical", + RegionTag: "US", Source: model.SourceMetadata{ SourceID: "fbi-wanted", AuthorityName: "FBI", @@ -67,14 +67,14 @@ func seedAlerts(t *testing.T, db *sourcedb.DB) { }, }, { - AlertID: "a3", - SourceID: "cert-ua", - Status: "active", - Title: "CERT-UA reports new malware campaign targeting energy sector", + AlertID: "a3", + SourceID: "cert-ua", + Status: "active", + Title: "CERT-UA reports new malware campaign targeting energy sector", CanonicalURL: "https://cert.gov.ua/a3", - Category: "cyber_advisory", - Severity: "high", - RegionTag: "UA", + Category: "cyber_advisory", + Severity: "high", + RegionTag: "UA", Source: model.SourceMetadata{ SourceID: "cert-ua", AuthorityName: "CERT-UA", diff --git a/internal/collector/discover/humanitarian.go b/internal/collector/discover/humanitarian.go index 5ca8e37..cd7dc1e 100644 --- a/internal/collector/discover/humanitarian.go +++ b/internal/collector/discover/humanitarian.go @@ -29,10 +29,10 @@ var humanitarianTypeIDs = []string{ "Q1460420", // civil protection "Q1066476", // emergency management // Subclasses we'd miss without P279* traversal: - "Q3918693", // emergency service - "Q863734", // rescue service - "Q167546", // NGO (filtered later by hygiene) - "Q484652", // international organization + "Q3918693", // emergency service + "Q863734", // rescue service + "Q167546", // NGO (filtered later by hygiene) + "Q484652", // international organization } func buildHumanitarianQuery(typeID string) string { diff --git a/internal/collector/discover/report.go b/internal/collector/discover/report.go index 81537d2..9b41bd9 100644 --- a/internal/collector/discover/report.go +++ b/internal/collector/discover/report.go @@ -10,9 +10,9 @@ import ( // DiscoveryReport is the JSON output structure for a discovery run. type DiscoveryReport struct { - NewCandidates []DiscoveredSource `json:"new_candidates"` - NewCandidateCount int `json:"new_candidate_count"` - ExistingFeedURLs int `json:"existing_feed_urls"` + NewCandidates []DiscoveredSource `json:"new_candidates"` + NewCandidateCount int `json:"new_candidate_count"` + ExistingFeedURLs int `json:"existing_feed_urls"` } // WriteReport writes the discovery results to the output path and logs diff --git a/internal/collector/discover/search_ddg_test.go b/internal/collector/discover/search_ddg_test.go index fab6848..29dd9c6 100644 --- a/internal/collector/discover/search_ddg_test.go +++ b/internal/collector/discover/search_ddg_test.go @@ -28,8 +28,8 @@ func TestExtractDDGURLs(t *testing.T) { // Should have 3 URLs (DDG internal filtered out). expected := map[string]bool{ - "https://www.ncsc.gov.uk/rss/all": false, - "https://www.cert.se/feed/rss.xml": false, + "https://www.ncsc.gov.uk/rss/all": false, + "https://www.cert.se/feed/rss.xml": false, "https://www.justice.gov/feeds/opa/justice-news.xml": false, } diff --git a/internal/collector/normalize/geocode.go b/internal/collector/normalize/geocode.go index 4fb9fc4..e9f25fc 100644 --- a/internal/collector/normalize/geocode.go +++ b/internal/collector/normalize/geocode.go @@ -175,98 +175,98 @@ var geoCountries = []countryGeo{ // the canonical country name used in geoCountries. var geoAliases = map[string]string{ // Adjective forms - "afghan": "Afghanistan", - "algerian": "Algeria", - "angolan": "Angola", - "argentine": "Argentina", - "armenian": "Armenia", - "azerbaijani": "Azerbaijan", - "bangladeshi": "Bangladesh", - "belarusian": "Belarus", - "bolivian": "Bolivia", - "bosnian": "Bosnia", - "brazilian": "Brazil", - "burmese": "Myanmar", - "burundian": "Burundi", - "cambodian": "Cambodia", - "cameroonian": "Cameroon", - "chadian": "Chad", - "chinese": "China", - "colombian": "Colombia", - "congolese": "Congo", - "cuban": "Cuba", - "ecuadorian": "Ecuador", - "egyptian": "Egypt", - "eritrean": "Eritrea", - "ethiopian": "Ethiopia", - "gambian": "Gambia", - "georgian": "Georgia", - "ghanaian": "Ghana", - "guatemalan": "Guatemala", - "guinean": "Guinea", - "haitian": "Haiti", - "honduran": "Honduras", - "indonesian": "Indonesia", - "iranian": "Iran", - "iraqi": "Iraq", - "israeli": "Israel", - "ivorian": "Ivory Coast", - "jordanian": "Jordan", - "kazakh": "Kazakhstan", - "kenyan": "Kenya", - "kosovar": "Kosovo", - "kuwaiti": "Kuwait", - "kyrgyz": "Kyrgyzstan", - "lebanese": "Lebanon", - "libyan": "Libya", - "malagasy": "Madagascar", - "malawian": "Malawi", - "malaysian": "Malaysia", - "malian": "Mali", - "maltese": "Malta", - "mauritanian": "Mauritania", - "mexican": "Mexico", - "moldovan": "Moldova", - "mongolian": "Mongolia", - "moroccan": "Morocco", - "mozambican": "Mozambique", - "namibian": "Namibia", - "nepalese": "Nepal", - "nicaraguan": "Nicaragua", - "nigerien": "Niger", - "nigerian": "Nigeria", - "pakistani": "Pakistan", - "palestinian": "Palestine", - "panamanian": "Panama", - "paraguayan": "Paraguay", - "peruvian": "Peru", - "philippine": "Philippines", - "qatari": "Qatar", - "romanian": "Romania", - "russian": "Russia", - "rwandan": "Rwanda", - "salvadoran": "El Salvador", - "saudi": "Saudi Arabia", - "senegalese": "Senegal", - "serbian": "Serbia", - "somali": "Somalia", - "sri lankan": "Sri Lanka", - "sudanese": "Sudan", - "syrian": "Syria", - "tajik": "Tajikistan", - "tanzanian": "Tanzania", - "thai": "Thailand", - "tunisian": "Tunisia", - "turkish": "Turkey", - "turkmen": "Turkmenistan", - "ugandan": "Uganda", - "ukrainian": "Ukraine", - "uzbek": "Uzbekistan", - "venezuelan": "Venezuela", - "vietnamese": "Vietnam", - "yemeni": "Yemen", - "zambian": "Zambia", - "zimbabwean": "Zimbabwe", + "afghan": "Afghanistan", + "algerian": "Algeria", + "angolan": "Angola", + "argentine": "Argentina", + "armenian": "Armenia", + "azerbaijani": "Azerbaijan", + "bangladeshi": "Bangladesh", + "belarusian": "Belarus", + "bolivian": "Bolivia", + "bosnian": "Bosnia", + "brazilian": "Brazil", + "burmese": "Myanmar", + "burundian": "Burundi", + "cambodian": "Cambodia", + "cameroonian": "Cameroon", + "chadian": "Chad", + "chinese": "China", + "colombian": "Colombia", + "congolese": "Congo", + "cuban": "Cuba", + "ecuadorian": "Ecuador", + "egyptian": "Egypt", + "eritrean": "Eritrea", + "ethiopian": "Ethiopia", + "gambian": "Gambia", + "georgian": "Georgia", + "ghanaian": "Ghana", + "guatemalan": "Guatemala", + "guinean": "Guinea", + "haitian": "Haiti", + "honduran": "Honduras", + "indonesian": "Indonesia", + "iranian": "Iran", + "iraqi": "Iraq", + "israeli": "Israel", + "ivorian": "Ivory Coast", + "jordanian": "Jordan", + "kazakh": "Kazakhstan", + "kenyan": "Kenya", + "kosovar": "Kosovo", + "kuwaiti": "Kuwait", + "kyrgyz": "Kyrgyzstan", + "lebanese": "Lebanon", + "libyan": "Libya", + "malagasy": "Madagascar", + "malawian": "Malawi", + "malaysian": "Malaysia", + "malian": "Mali", + "maltese": "Malta", + "mauritanian": "Mauritania", + "mexican": "Mexico", + "moldovan": "Moldova", + "mongolian": "Mongolia", + "moroccan": "Morocco", + "mozambican": "Mozambique", + "namibian": "Namibia", + "nepalese": "Nepal", + "nicaraguan": "Nicaragua", + "nigerien": "Niger", + "nigerian": "Nigeria", + "pakistani": "Pakistan", + "palestinian": "Palestine", + "panamanian": "Panama", + "paraguayan": "Paraguay", + "peruvian": "Peru", + "philippine": "Philippines", + "qatari": "Qatar", + "romanian": "Romania", + "russian": "Russia", + "rwandan": "Rwanda", + "salvadoran": "El Salvador", + "saudi": "Saudi Arabia", + "senegalese": "Senegal", + "serbian": "Serbia", + "somali": "Somalia", + "sri lankan": "Sri Lanka", + "sudanese": "Sudan", + "syrian": "Syria", + "tajik": "Tajikistan", + "tanzanian": "Tanzania", + "thai": "Thailand", + "tunisian": "Tunisia", + "turkish": "Turkey", + "turkmen": "Turkmenistan", + "ugandan": "Uganda", + "ukrainian": "Ukraine", + "uzbek": "Uzbekistan", + "venezuelan": "Venezuela", + "vietnamese": "Vietnam", + "yemeni": "Yemen", + "zambian": "Zambia", + "zimbabwean": "Zimbabwe", // Alternative / short names "drc": "Congo", @@ -282,62 +282,62 @@ var geoAliases = map[string]string{ "british": "United Kingdom", // Conflict regions / sub-national areas → parent country - "tigray": "Ethiopia", - "amhara": "Ethiopia", - "oromia": "Ethiopia", - "rakhine": "Myanmar", - "shan": "Myanmar", - "kachin": "Myanmar", - "darfur": "Sudan", - "kordofan": "Sudan", - "blue nile": "Sudan", - "donbas": "Ukraine", - "donbass": "Ukraine", - "donetsk": "Ukraine", - "luhansk": "Ukraine", - "crimea": "Ukraine", - "kherson": "Ukraine", - "zaporizhzhia": "Ukraine", - "idlib": "Syria", - "aleppo": "Syria", - "golan": "Syria", - "sinai": "Egypt", - "sahel": "Mali", - "cabo delgado": "Mozambique", - "kivu": "Congo", - "ituri": "Congo", - "kasai": "Congo", - "west bank": "Palestine", - "hebron": "Palestine", - "jenin": "Palestine", - "nablus": "Palestine", - "rafah": "Gaza", - "khan younis": "Gaza", - "balochistan": "Pakistan", - "waziristan": "Pakistan", - "kashmir": "India", + "tigray": "Ethiopia", + "amhara": "Ethiopia", + "oromia": "Ethiopia", + "rakhine": "Myanmar", + "shan": "Myanmar", + "kachin": "Myanmar", + "darfur": "Sudan", + "kordofan": "Sudan", + "blue nile": "Sudan", + "donbas": "Ukraine", + "donbass": "Ukraine", + "donetsk": "Ukraine", + "luhansk": "Ukraine", + "crimea": "Ukraine", + "kherson": "Ukraine", + "zaporizhzhia": "Ukraine", + "idlib": "Syria", + "aleppo": "Syria", + "golan": "Syria", + "sinai": "Egypt", + "sahel": "Mali", + "cabo delgado": "Mozambique", + "kivu": "Congo", + "ituri": "Congo", + "kasai": "Congo", + "west bank": "Palestine", + "hebron": "Palestine", + "jenin": "Palestine", + "nablus": "Palestine", + "rafah": "Gaza", + "khan younis": "Gaza", + "balochistan": "Pakistan", + "waziristan": "Pakistan", + "kashmir": "India", "nagorno-karabakh": "Azerbaijan", - "karabakh": "Azerbaijan", - "mindanao": "Philippines", - "marawi": "Philippines", - "helmand": "Afghanistan", - "kandahar": "Afghanistan", - "kabul": "Afghanistan", - "mogadishu": "Somalia", - "benghazi": "Libya", - "tripoli": "Libya", - "mosul": "Iraq", - "kirkuk": "Iraq", - "basra": "Iraq", - "aden": "Yemen", - "sanaa": "Yemen", - "marib": "Yemen", - "hodeida": "Yemen", - "hodeidah": "Yemen", - "taipei": "Taiwan", - "valletta": "Malta", - "kyiv": "Ukraine", - "kharkiv": "Ukraine", + "karabakh": "Azerbaijan", + "mindanao": "Philippines", + "marawi": "Philippines", + "helmand": "Afghanistan", + "kandahar": "Afghanistan", + "kabul": "Afghanistan", + "mogadishu": "Somalia", + "benghazi": "Libya", + "tripoli": "Libya", + "mosul": "Iraq", + "kirkuk": "Iraq", + "basra": "Iraq", + "aden": "Yemen", + "sanaa": "Yemen", + "marib": "Yemen", + "hodeida": "Yemen", + "hodeidah": "Yemen", + "taipei": "Taiwan", + "valletta": "Malta", + "kyiv": "Ukraine", + "kharkiv": "Ukraine", } // geoIndex maps lowercased country names to their centroid. Built once at init. @@ -386,8 +386,8 @@ func geocodeCountryCode(code string) (lat, lng float64, name string, ok bool) { func geocodeText(text string) (lat, lng float64, code string, ok bool) { lower := strings.ToLower(text) - bestPos := -1 // rightmost end-position of best match - bestLen := 0 // length of best match (tiebreaker) + bestPos := -1 // rightmost end-position of best match + bestLen := 0 // length of best match (tiebreaker) var bestGeo *countryGeo for key, g := range geoIndex { diff --git a/internal/collector/normalize/geocode_capitals.go b/internal/collector/normalize/geocode_capitals.go index ee2a524..d51d51d 100644 --- a/internal/collector/normalize/geocode_capitals.go +++ b/internal/collector/normalize/geocode_capitals.go @@ -7,157 +7,157 @@ package normalize // Used instead of geographic centroids so island nations (Malta, Cyprus, // Singapore, etc.) place pins on land rather than in the sea. var capitalCoords = map[string][2]float64{ - "AF": {34.53, 69.17}, // Kabul - "AL": {41.33, 19.82}, // Tirana - "DZ": {36.75, 3.04}, // Algiers - "AO": {-8.84, 13.23}, // Luanda + "AF": {34.53, 69.17}, // Kabul + "AL": {41.33, 19.82}, // Tirana + "DZ": {36.75, 3.04}, // Algiers + "AO": {-8.84, 13.23}, // Luanda "AR": {-34.60, -58.38}, // Buenos Aires - "AM": {40.18, 44.51}, // Yerevan + "AM": {40.18, 44.51}, // Yerevan "AU": {-35.28, 149.13}, // Canberra - "AT": {48.21, 16.37}, // Vienna - "AZ": {40.41, 49.87}, // Baku - "BH": {26.23, 50.59}, // Manama - "BD": {23.81, 90.41}, // Dhaka - "BY": {53.90, 27.57}, // Minsk - "BE": {50.85, 4.35}, // Brussels - "BJ": {6.50, 2.60}, // Porto-Novo + "AT": {48.21, 16.37}, // Vienna + "AZ": {40.41, 49.87}, // Baku + "BH": {26.23, 50.59}, // Manama + "BD": {23.81, 90.41}, // Dhaka + "BY": {53.90, 27.57}, // Minsk + "BE": {50.85, 4.35}, // Brussels + "BJ": {6.50, 2.60}, // Porto-Novo "BO": {-16.50, -68.15}, // La Paz - "BA": {43.86, 18.41}, // Sarajevo - "BW": {-24.65, 25.91}, // Gaborone + "BA": {43.86, 18.41}, // Sarajevo + "BW": {-24.65, 25.91}, // Gaborone "BR": {-15.79, -47.88}, // Brasília - "BG": {42.70, 23.32}, // Sofia - "BF": {12.37, -1.52}, // Ouagadougou - "BI": {-3.38, 29.36}, // Gitega - "KH": {11.56, 104.92}, // Phnom Penh - "CM": {3.87, 11.52}, // Yaoundé - "CA": {45.42, -75.70}, // Ottawa - "CF": {4.39, 18.56}, // Bangui - "TD": {12.13, 15.05}, // N'Djamena + "BG": {42.70, 23.32}, // Sofia + "BF": {12.37, -1.52}, // Ouagadougou + "BI": {-3.38, 29.36}, // Gitega + "KH": {11.56, 104.92}, // Phnom Penh + "CM": {3.87, 11.52}, // Yaoundé + "CA": {45.42, -75.70}, // Ottawa + "CF": {4.39, 18.56}, // Bangui + "TD": {12.13, 15.05}, // N'Djamena "CL": {-33.45, -70.67}, // Santiago - "CN": {39.90, 116.40}, // Beijing - "CO": {4.71, -74.07}, // Bogotá - "CD": {-4.32, 15.31}, // Kinshasa - "CR": {9.93, -84.09}, // San José - "HR": {45.81, 15.98}, // Zagreb - "CU": {23.11, -82.37}, // Havana - "CY": {35.17, 33.36}, // Nicosia - "CZ": {50.08, 14.43}, // Prague - "DK": {55.68, 12.57}, // Copenhagen - "DO": {18.47, -69.90}, // Santo Domingo - "EC": {-0.18, -78.47}, // Quito - "EG": {30.04, 31.24}, // Cairo - "SV": {13.69, -89.19}, // San Salvador - "ER": {15.34, 38.93}, // Asmara - "EE": {59.44, 24.75}, // Tallinn - "ET": {9.02, 38.75}, // Addis Ababa - "FI": {60.17, 24.94}, // Helsinki - "FR": {48.86, 2.35}, // Paris - "GA": {0.39, 9.45}, // Libreville - "GM": {13.45, -16.58}, // Banjul - "PS": {31.90, 35.20}, // Ramallah - "GE": {41.72, 44.79}, // Tbilisi - "DE": {52.52, 13.41}, // Berlin - "GH": {5.56, -0.19}, // Accra - "GR": {37.98, 23.73}, // Athens - "GT": {14.63, -90.51}, // Guatemala City - "GN": {9.64, -13.58}, // Conakry - "HT": {18.54, -72.34}, // Port-au-Prince - "HN": {14.07, -87.19}, // Tegucigalpa - "HU": {47.50, 19.04}, // Budapest - "IN": {28.61, 77.21}, // New Delhi - "ID": {-6.21, 106.85}, // Jakarta - "IR": {35.69, 51.39}, // Tehran - "IQ": {33.34, 44.37}, // Baghdad - "IE": {53.35, -6.26}, // Dublin - "IL": {31.77, 35.22}, // Jerusalem - "IT": {41.90, 12.50}, // Rome - "CI": {6.83, -5.29}, // Yamoussoukro - "JM": {18.00, -76.79}, // Kingston - "JP": {35.68, 139.69}, // Tokyo - "JO": {31.95, 35.93}, // Amman - "KZ": {51.17, 71.43}, // Astana - "KE": {-1.29, 36.82}, // Nairobi - "XK": {42.66, 21.17}, // Pristina - "KW": {29.37, 47.98}, // Kuwait City - "KG": {42.87, 74.59}, // Bishkek - "LA": {17.97, 102.63}, // Vientiane - "LV": {56.95, 24.11}, // Riga - "LB": {33.89, 35.50}, // Beirut - "LY": {32.90, 13.18}, // Tripoli - "LT": {54.69, 25.28}, // Vilnius - "LU": {49.61, 6.13}, // Luxembourg City - "MG": {-18.91, 47.54}, // Antananarivo - "MW": {-13.97, 33.79}, // Lilongwe - "MY": {3.14, 101.69}, // Kuala Lumpur - "ML": {12.64, -8.00}, // Bamako - "MT": {35.90, 14.51}, // Valletta - "MR": {18.09, -15.98}, // Nouakchott - "MX": {19.43, -99.13}, // Mexico City - "MD": {47.01, 28.86}, // Chișinău - "MN": {47.91, 106.91}, // Ulaanbaatar - "ME": {42.44, 19.26}, // Podgorica - "MA": {34.02, -6.84}, // Rabat - "MZ": {-25.97, 32.57}, // Maputo - "MM": {19.76, 96.07}, // Naypyidaw - "NA": {-22.56, 17.08}, // Windhoek - "NP": {27.72, 85.32}, // Kathmandu - "NL": {52.37, 4.89}, // Amsterdam + "CN": {39.90, 116.40}, // Beijing + "CO": {4.71, -74.07}, // Bogotá + "CD": {-4.32, 15.31}, // Kinshasa + "CR": {9.93, -84.09}, // San José + "HR": {45.81, 15.98}, // Zagreb + "CU": {23.11, -82.37}, // Havana + "CY": {35.17, 33.36}, // Nicosia + "CZ": {50.08, 14.43}, // Prague + "DK": {55.68, 12.57}, // Copenhagen + "DO": {18.47, -69.90}, // Santo Domingo + "EC": {-0.18, -78.47}, // Quito + "EG": {30.04, 31.24}, // Cairo + "SV": {13.69, -89.19}, // San Salvador + "ER": {15.34, 38.93}, // Asmara + "EE": {59.44, 24.75}, // Tallinn + "ET": {9.02, 38.75}, // Addis Ababa + "FI": {60.17, 24.94}, // Helsinki + "FR": {48.86, 2.35}, // Paris + "GA": {0.39, 9.45}, // Libreville + "GM": {13.45, -16.58}, // Banjul + "PS": {31.90, 35.20}, // Ramallah + "GE": {41.72, 44.79}, // Tbilisi + "DE": {52.52, 13.41}, // Berlin + "GH": {5.56, -0.19}, // Accra + "GR": {37.98, 23.73}, // Athens + "GT": {14.63, -90.51}, // Guatemala City + "GN": {9.64, -13.58}, // Conakry + "HT": {18.54, -72.34}, // Port-au-Prince + "HN": {14.07, -87.19}, // Tegucigalpa + "HU": {47.50, 19.04}, // Budapest + "IN": {28.61, 77.21}, // New Delhi + "ID": {-6.21, 106.85}, // Jakarta + "IR": {35.69, 51.39}, // Tehran + "IQ": {33.34, 44.37}, // Baghdad + "IE": {53.35, -6.26}, // Dublin + "IL": {31.77, 35.22}, // Jerusalem + "IT": {41.90, 12.50}, // Rome + "CI": {6.83, -5.29}, // Yamoussoukro + "JM": {18.00, -76.79}, // Kingston + "JP": {35.68, 139.69}, // Tokyo + "JO": {31.95, 35.93}, // Amman + "KZ": {51.17, 71.43}, // Astana + "KE": {-1.29, 36.82}, // Nairobi + "XK": {42.66, 21.17}, // Pristina + "KW": {29.37, 47.98}, // Kuwait City + "KG": {42.87, 74.59}, // Bishkek + "LA": {17.97, 102.63}, // Vientiane + "LV": {56.95, 24.11}, // Riga + "LB": {33.89, 35.50}, // Beirut + "LY": {32.90, 13.18}, // Tripoli + "LT": {54.69, 25.28}, // Vilnius + "LU": {49.61, 6.13}, // Luxembourg City + "MG": {-18.91, 47.54}, // Antananarivo + "MW": {-13.97, 33.79}, // Lilongwe + "MY": {3.14, 101.69}, // Kuala Lumpur + "ML": {12.64, -8.00}, // Bamako + "MT": {35.90, 14.51}, // Valletta + "MR": {18.09, -15.98}, // Nouakchott + "MX": {19.43, -99.13}, // Mexico City + "MD": {47.01, 28.86}, // Chișinău + "MN": {47.91, 106.91}, // Ulaanbaatar + "ME": {42.44, 19.26}, // Podgorica + "MA": {34.02, -6.84}, // Rabat + "MZ": {-25.97, 32.57}, // Maputo + "MM": {19.76, 96.07}, // Naypyidaw + "NA": {-22.56, 17.08}, // Windhoek + "NP": {27.72, 85.32}, // Kathmandu + "NL": {52.37, 4.89}, // Amsterdam "NZ": {-41.29, 174.78}, // Wellington - "NI": {12.11, -86.27}, // Managua - "NE": {13.51, 2.11}, // Niamey - "NG": {9.06, 7.49}, // Abuja - "KP": {39.02, 125.75}, // Pyongyang - "MK": {42.00, 21.43}, // Skopje - "NO": {59.91, 10.75}, // Oslo - "OM": {23.59, 58.54}, // Muscat - "PK": {33.69, 73.04}, // Islamabad - "PA": {8.98, -79.52}, // Panama City - "PG": {-6.31, 147.15}, // Port Moresby + "NI": {12.11, -86.27}, // Managua + "NE": {13.51, 2.11}, // Niamey + "NG": {9.06, 7.49}, // Abuja + "KP": {39.02, 125.75}, // Pyongyang + "MK": {42.00, 21.43}, // Skopje + "NO": {59.91, 10.75}, // Oslo + "OM": {23.59, 58.54}, // Muscat + "PK": {33.69, 73.04}, // Islamabad + "PA": {8.98, -79.52}, // Panama City + "PG": {-6.31, 147.15}, // Port Moresby "PY": {-25.26, -57.58}, // Asunción "PE": {-12.05, -77.04}, // Lima - "PH": {14.60, 120.98}, // Manila - "PL": {52.23, 21.01}, // Warsaw - "PT": {38.72, -9.14}, // Lisbon - "QA": {25.29, 51.53}, // Doha - "RO": {44.43, 26.10}, // Bucharest - "RU": {55.76, 37.62}, // Moscow - "RW": {-1.94, 30.06}, // Kigali - "SA": {24.69, 46.72}, // Riyadh - "SN": {14.72, -17.47}, // Dakar - "RS": {44.79, 20.47}, // Belgrade - "SL": {8.48, -13.23}, // Freetown - "SG": {1.29, 103.85}, // Singapore - "SK": {48.15, 17.11}, // Bratislava - "SI": {46.06, 14.51}, // Ljubljana - "SO": {2.05, 45.32}, // Mogadishu - "ZA": {-25.75, 28.19}, // Pretoria - "KR": {37.57, 126.98}, // Seoul - "SS": {4.85, 31.60}, // Juba - "ES": {40.42, -3.70}, // Madrid - "LK": {6.93, 79.85}, // Colombo - "SD": {15.60, 32.53}, // Khartoum - "SE": {59.33, 18.07}, // Stockholm - "CH": {46.95, 7.45}, // Bern - "SY": {33.51, 36.28}, // Damascus - "TW": {25.03, 121.57}, // Taipei - "TJ": {38.56, 68.77}, // Dushanbe - "TZ": {-6.16, 35.75}, // Dodoma - "TH": {13.76, 100.50}, // Bangkok - "TG": {6.14, 1.21}, // Lomé - "TN": {36.81, 10.17}, // Tunis - "TR": {39.93, 32.87}, // Ankara - "TM": {37.95, 58.38}, // Ashgabat - "UG": {0.35, 32.58}, // Kampala - "UA": {50.45, 30.52}, // Kyiv - "AE": {24.45, 54.65}, // Abu Dhabi - "GB": {51.51, -0.13}, // London - "US": {38.90, -77.04}, // Washington D.C. + "PH": {14.60, 120.98}, // Manila + "PL": {52.23, 21.01}, // Warsaw + "PT": {38.72, -9.14}, // Lisbon + "QA": {25.29, 51.53}, // Doha + "RO": {44.43, 26.10}, // Bucharest + "RU": {55.76, 37.62}, // Moscow + "RW": {-1.94, 30.06}, // Kigali + "SA": {24.69, 46.72}, // Riyadh + "SN": {14.72, -17.47}, // Dakar + "RS": {44.79, 20.47}, // Belgrade + "SL": {8.48, -13.23}, // Freetown + "SG": {1.29, 103.85}, // Singapore + "SK": {48.15, 17.11}, // Bratislava + "SI": {46.06, 14.51}, // Ljubljana + "SO": {2.05, 45.32}, // Mogadishu + "ZA": {-25.75, 28.19}, // Pretoria + "KR": {37.57, 126.98}, // Seoul + "SS": {4.85, 31.60}, // Juba + "ES": {40.42, -3.70}, // Madrid + "LK": {6.93, 79.85}, // Colombo + "SD": {15.60, 32.53}, // Khartoum + "SE": {59.33, 18.07}, // Stockholm + "CH": {46.95, 7.45}, // Bern + "SY": {33.51, 36.28}, // Damascus + "TW": {25.03, 121.57}, // Taipei + "TJ": {38.56, 68.77}, // Dushanbe + "TZ": {-6.16, 35.75}, // Dodoma + "TH": {13.76, 100.50}, // Bangkok + "TG": {6.14, 1.21}, // Lomé + "TN": {36.81, 10.17}, // Tunis + "TR": {39.93, 32.87}, // Ankara + "TM": {37.95, 58.38}, // Ashgabat + "UG": {0.35, 32.58}, // Kampala + "UA": {50.45, 30.52}, // Kyiv + "AE": {24.45, 54.65}, // Abu Dhabi + "GB": {51.51, -0.13}, // London + "US": {38.90, -77.04}, // Washington D.C. "UY": {-34.88, -56.17}, // Montevideo - "UZ": {41.30, 69.28}, // Tashkent - "VE": {10.49, -66.88}, // Caracas - "VN": {21.03, 105.85}, // Hanoi - "YE": {15.37, 44.21}, // Sana'a - "ZM": {-15.39, 28.32}, // Lusaka - "ZW": {-17.83, 31.05}, // Harare - "IS": {64.15, -21.94}, // Reykjavik + "UZ": {41.30, 69.28}, // Tashkent + "VE": {10.49, -66.88}, // Caracas + "VN": {21.03, 105.85}, // Hanoi + "YE": {15.37, 44.21}, // Sana'a + "ZM": {-15.39, 28.32}, // Lusaka + "ZW": {-17.83, 31.05}, // Harare + "IS": {64.15, -21.94}, // Reykjavik } diff --git a/internal/collector/normalize/geocode_nominatim.go b/internal/collector/normalize/geocode_nominatim.go index 29ddf99..4cdbfb6 100644 --- a/internal/collector/normalize/geocode_nominatim.go +++ b/internal/collector/normalize/geocode_nominatim.go @@ -176,4 +176,3 @@ func (n *NominatimClient) CacheStats() (total int, hits int) { } return total, hits } - diff --git a/internal/collector/parse/fbi.go b/internal/collector/parse/fbi.go index ab4c2df..09c9f38 100644 --- a/internal/collector/parse/fbi.go +++ b/internal/collector/parse/fbi.go @@ -123,4 +123,3 @@ func buildFBITags(entry FBIWantedEntry) []string { } return tags } - diff --git a/internal/sourcedb/db.go b/internal/sourcedb/db.go index 3ec3c1c..90f6c20 100644 --- a/internal/sourcedb/db.go +++ b/internal/sourcedb/db.go @@ -676,11 +676,11 @@ LIMIT ?`, args...) var results []model.Alert for rows.Next() { var ( - a model.Alert - sourceJSON string - reportJSON string - triageJSON string - rank float64 + a model.Alert + sourceJSON string + reportJSON string + triageJSON string + rank float64 ) if err := rows.Scan(&a.AlertID, &a.SourceID, &a.Status, &a.FirstSeen, &a.LastSeen, &a.Title, &a.CanonicalURL, &a.Category, &a.Severity, &a.RegionTag,