Files
osint_db/migrations/005_network_scans.sql
egutierrez 3063d3c44f feat(scans): persistencia de escaneos de red + POST /api/scan
Tabla network_scans (migración 005, schema main, lleva note_path) que otras
herramientas pueblan vía HTTP con escaneos de reconocimiento (whois/rdap/dns/
nmap/traceroute/ping). Endpoint POST /api/scan: id determinista
<target_slug>:<scan_type>:<YYYYMMDD-HHMM> derivado de scan_ts, idempotente por
id (duckdb_upsert ON CONFLICT DO UPDATE) bajo el lock single-writer del service.
summary (dict) se serializa a JSON.

network_scans no se deriva de notas: ni ingest_vault ni ingest_dav la tocan, así
que un re-ingest del vault no la trunca (test lo verifica).

Tests: inserción + id derivado, idempotencia mismo-minuto, validación de campos
requeridos (422), y no-truncado por ingest del vault.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 13:13:36 +02:00

32 lines
1.5 KiB
SQL

-- Migración 005: tabla de escaneos de red (network_scans).
--
-- Persistencia de escaneos de reconocimiento de red (whois, rdap, dns, nmap,
-- traceroute, ping) que otras herramientas del ecosistema OSINT registran vía
-- HTTP en POST /api/scan. Vive en el schema main (no en derived) porque lleva
-- note_path: cada escaneo referencia la nota .md del vault donde se documenta su
-- salida (dominios/<slug>/recon/<...>.md). La regla dura "derived sin note_path"
-- no aplica aquí — esta es una maestra con referencia a notas, igual que persons
-- o contacts.
--
-- A diferencia de las maestras de espejo puro (notes, organizations, ...) y de
-- las DAV (contacts, events), network_scans NO se reconstruye en ningún ingest:
-- la pueblan los escaneos vía /api/scan y nunca se trunca. Por eso ni
-- ingest_vault ni ingest_dav la tocan.
--
-- Aditiva e idempotente: CREATE TABLE IF NOT EXISTS + CREATE INDEX IF NOT EXISTS.
CREATE TABLE IF NOT EXISTS network_scans (
id VARCHAR PRIMARY KEY, -- "<target_slug>:<scan_type>:<ts_compact>"
target VARCHAR NOT NULL,
target_slug VARCHAR NOT NULL,
scan_type VARCHAR NOT NULL, -- whois|rdap|dns|nmap|traceroute|ping
tool VARCHAR,
scan_ts TIMESTAMP NOT NULL,
note_path VARCHAR NOT NULL, -- dominios/<slug>/recon/<...>.md
summary JSON,
created_at TIMESTAMP DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_network_scans_slug ON network_scans(target_slug);
CREATE INDEX IF NOT EXISTS idx_network_scans_type ON network_scans(scan_type);