It started as a single HTML file. A list of attackers.
It became a full forensic pipeline — honeypot to evidence, evidence to investigation,
investigation to published article — with every piece of data vectorized, cross-linked, and
searchable in milliseconds. 115,601 vectors. 21 Qdrant collections. 3 PostgreSQL databases. 14 autonomous CronJobs. One machine.
📜 Origin
The first threat intelligence dossier was a block of HTML hand-spliced into a monolithic page. Editing meant counting divs. Publishing meant a grep and a copy. Linking evidence meant trusting memory. That wasn't a methodology — it was archaeology in reverse.
A single threat-intel.html file containing every published dossier as raw HTML sections. No structure. No queryability. No versioning beyond manual git commits. Dossiers 001–025 still live there — a museum of the before.
A REST API that decoupled content from structure. Each dossier became a database record: slug, title, HTML content, scoped CSS, series order, navigation position. Publishing became a POST request. The nav rebuilt itself. Every page regenerated from a single source of truth. AI agents can now write Markdown and the pipeline auto-converts to themed, styled articles — no raw HTML required.
The articles were the visible surface. What they rested on was the real work: a structured dossier_intel PostgreSQL database holding every actor, finding, evidence item, infrastructure node, and connection that fed each published report. Nothing published without a citation. Nothing cited without a source URL.
8,375 NLP-enriched chunks from court filings, WikiLeaks cables, sanctions lists, ODNI reports, dark web takedown records, and corporate surveillance documents. Fed through FSCrawler into Elasticsearch, then embedded into Qdrant via bge-m3. Every investigation can now cite a DOJ indictment or a WikiLeaks cable with a real source URL — not a paraphrase.
Everything that existed — published articles, evidence, actors, findings, infrastructure nodes, connections, investigation summaries, OSINT library chunks — got embedded into Qdrant. Not a backup. A live semantic index. Any AI agent can now ask "what else is connected to this IP?" and traverse 17,237 entity crosslinks across 21 collections in one call.
The honeypot watched SSH. But what was hitting the HTTP surface? Traefik logs, CrowdSec L7 decisions, and MikroTik L3 ban lists sat in separate systems with no unified intelligence. A new API, database, and indexer pulled them together: 7,485 IP profiles, 36 campaigns, 95 ASN threat profiles, 1M+ CrowdSec decisions — all searchable, all linked into the same Qdrant graph as the honeypot and the dossiers.
⚙️ Architecture
Each layer feeds the next. None of them require cloud. All of them run on one machine in Iași, Romania.
threat_intel in real time. Enriched hourly with RDAP, Cymru BGP, Shodan, GreyNoise, OTX, VirusTotal, Censys, DShield, IPInfo.dossier_intel holds every forensic artifact: actors with institutional anchors, findings with confidence levels, evidence with source URLs, infrastructure nodes, connection graphs, and investigation timelines. 817 investigations. 279 published.bge-m3.bge-m3. Honeypot IPs, dossier findings, published article chunks, OSINT library documents, entity crosslinks — all in one semantic graph. Any AI agent can traverse the entire intelligence picture in a single query.🔀 Data Flow
Every dossier on this site follows the same chain. Nothing published without passing through every layer.
🗄️ Storage
Each database has a distinct role. No single system holds everything. They feed each other through enrichment jobs, entity linkers, and the indexing pipeline.
📊 The Memory
Every data type gets its own Qdrant collection, with filtered search indexes. Entity crosslinks bridge them: a finding in a dossier links to an IP in the honeypot links to an ASN in web threats links to a court filing in the OSINT library.
| Collection | Domain | Vectors | Contents |
|---|---|---|---|
dossier_findings | Investigations | 3,352 | Analytical conclusions with confidence, severity, category |
dossier_evidence | Investigations | 9,573 | Sourced evidence items — every claim traceable to a URL |
dossier_actors | Investigations | 2,180 | Actors and entities with type, risk, country, institutional anchors |
dossier_infrastructure | Investigations | 3,483 | IPs, ASNs, domains, hosting providers used by tracked actors |
dossier_connections | Investigations | 5,042 | Relationship edges between entities — directional, typed, confidence-rated |
dossier_published | Investigations | 4,097 | Published article content chunks — search across actual dossier text |
dossier_investigations | Investigations | 918 | Investigation summaries and metadata — find related cases |
dossier_osint_library | OSINT Library | 8,375 | Court filings, WikiLeaks, sanctions, intel reports, dark web takedowns |
honeypot_ips | Honeypot | 9,978 | Full IP threat profiles — behavior, enrichment, attribution, campaigns |
honeypot_asns | Honeypot | 2,059 | ASN-level risk profiles — country, bulletproof status, attack volume |
honeypot_orgs | Honeypot | 1,738 | Organization threat profiles — hosting patterns, operator clustering |
honeypot_campaigns | Honeypot | 57 | Detected coordinated attack campaigns — IPs, timing, shared signatures |
honeypot_sessions | Honeypot | 1,231 | SSH session intelligence — command patterns, HASSH clusters, tooling |
honeypot_actors | Honeypot | 14 | HASSH-based actor cluster profiles |
web_threats_ips | Web Threats | 7,479 | HTTP-layer IP profiles — Traefik patterns, CrowdSec bans, MikroTik blocks |
web_threats_campaigns | Web Threats | 36 | Auto-detected HTTP attack campaigns — shared paths, timing, signatures |
web_threats_asns | Web Threats | 95 | ASN risk profiles from the HTTP observation point |
entity_crosslinks | Graph | 16,050 | Auto-generated edges connecting honeypot ↔ dossiers ↔ web threats ↔ OSINT library |
🕵️ Method
Every published dossier follows the same seven-layer methodology. Not because a framework said so — because each layer catches what the others miss.
threat_intel PostgreSQL, HASSH fingerprints, SSH key sharing, ASN/BGP/RDAP registration chains, Shodan banners, certificate histories.Before publishing, the strongest alternative explanation is generated. If the evidence doesn't survive its own counter-narrative, the dossier isn't ready.
Quality gate applied to all 279 published investigations🤖 AI Integration
The vectorization wasn't built for search. It was built so that any connected AI model inherits 115,601 vectors of forensic context the moment it connects — no retrieval prompt engineering, no manually curated examples.
/dossier-toolkit directory of structured documentation — methodology guides, database schemas, publishing workflows, investigation principles — loaded by dossier_guide(topic). The AI reads the actual operating manual, not a cached version of it.db-payload.jsonl (audit log of all writes), category dumps (actors, evidence, findings), raw research notes. Mounted into the MCP server. Persistent across sessions. The AI's work survives restarts.The goal wasn't to make AI useful for threat intelligence. It was to make 115,000 vectors of forensic context available to whatever AI model asks for them — without rebuilding the pipeline for each model.
Architecture decision — December 2025📂 Explore
The dossiers are the published surface. The platform is what makes them defensible.