Concurrent, rate-limited feed ingestion wired end to end: 'scrape' pulls live security news into the SQLite store, idempotent across re-runs. - internal/fetch: per-host token-bucket rate limiting, conditional GET (ETag/Last-Modified with 304 handling), retry+backoff that honors Retry-After and treats timeouts/cancellation as non-retryable, per-source deadline, honest User-Agent, 16MB body cap. robots.txt is enforced only via Client.Allowed() for the future HTML article-scrape path, not on subscribed feed fetches (user-directed retrieval; several publishers blanket-disallow generic bots yet serve a public feed). - internal/parse: gofeed RSS/Atom to a normalized Item; RFC1123Z/RFC822Z/ RFC3339 time fallbacks (CISA emits RFC822Z, not RFC1123Z as first researched). - internal/normalize: canonical URL (lowercase scheme+host, drop fragment, strip utm_*/gclid/fbclid/ref/mc_cid/mc_eid, drop trailing slash), title normalization, goquery HTML strip, sha256 content+title hashes. - internal/ingest: errgroup fan-out over sources, fail-soft per source, fetch -> parse -> normalize -> InsertArticle dedup via store.ErrDuplicate, plus fetch_state upsert for conditional GET. - store: migration 0002 adds articles.title_hash; GetFetchState/UpsertFetchState. - Trimmed testdata/feeds fixtures (3 items each) back golden parse tests; full suite is offline and passes under -race. Proven live: cold run 215 new across 7 sources, warm run 0 new (304s + dedup). Ctrl-C aborts scrape cleanly via signal-aware context. |
||
|---|---|---|
| .. | ||
| cmd/nadezhda | ||
| internal | ||
| testdata/feeds | ||
| .gitignore | ||
| README.md | ||
| go.mod | ||
| go.sum | ||
| justfile | ||
README.md
Nadezhda
A concurrent security-news and CVE aggregation engine, written in Go.
Nadezhda ingests cybersecurity news from reliable RSS feeds, enriches every referenced CVE with authoritative exploit intelligence (NVD, CISA KEV, FIRST EPSS), clusters the same story across outlets, ranks items by real-world significance, and surfaces content angles. It ships as a single static binary with a local SQLite store, a colorful terminal UI, and Markdown/JSON export.
Status
Early development. The scaffold is in place: configuration, source registry, SQLite store with forward-only migrations, and the command skeleton.
nadezhda version # print version
nadezhda sources # list configured feeds and persist them to the store
Ingestion, CVE enrichment, ranking, the TUI, and the AI ideation layer land in subsequent milestones.
Build
just build # -> ./nadezhda
just test
Requires Go 1.25+.
Full documentation lands in learn/ as the project matures.