0e7b615a1e
- CONVENTIONS.md - tools/gen_osint_tools.py Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
280 lines
11 KiB
Markdown
280 lines
11 KiB
Markdown
# Convenciones de archivos — vault osint
|
|
|
|
Estándar para organizar la información de personas (y, a futuro, dominios y casos) en el vault
|
|
`osint` (`/home/enmanuel/Obsidian/osint`). Toda extracción desde otros vaults o desde sesiones
|
|
de navegación OSINT debe dejar los archivos siguiendo este estándar.
|
|
|
|
## 1. Estructura física (estándar: plano + subcarpeta de documentos)
|
|
|
|
```
|
|
osint/
|
|
README.md
|
|
_self.md # ficha del titular (Enmanuel), referencia, NO es objetivo
|
|
personas/
|
|
<slug>.md # ficha de la persona (su "index")
|
|
<slug>/ # carpeta con las notas-documento de esa persona
|
|
<doc-slug>.md
|
|
dominios/
|
|
organizaciones/ # empresas/entidades (mismo patrón <slug>.md + <slug>/)
|
|
lugares/ # direcciones/lugares de interés
|
|
casos/
|
|
inbox/
|
|
attachments/
|
|
personas/
|
|
<slug>/
|
|
<doc-slug>-NN.<ext> # imágenes/PDFs de esa persona
|
|
```
|
|
|
|
Regla: la ficha vive como `.md` suelto en `personas/` (todas las fichas listables en un nivel);
|
|
sus documentos en una subcarpeta homónima; los binarios en `attachments/personas/<slug>/`.
|
|
|
|
## 2. Slug
|
|
|
|
El `slug` es la clave estable de una persona. Se deriva del nombre completo:
|
|
|
|
- minúsculas, sin acentos ni `ñ` (transliteración: `ñ`→`n`, `á`→`a`, …)
|
|
- espacios y separadores → `-`
|
|
- solo `[a-z0-9-]`, sin guiones dobles ni al inicio/fin
|
|
|
|
Ejemplo: `Enmanuel Gutiérrez Pérez` → `enmanuel-gutierrez-perez`.
|
|
|
|
## 3. Ficha de persona — `personas/<slug>.md`
|
|
|
|
Frontmatter:
|
|
|
|
```yaml
|
|
tipo: persona
|
|
nombre: "Enmanuel Gutierrez Perez" # nombre legible original
|
|
aliases: ["Enmanuel Gutierrez Perez"] # nombres viejos para que wikilinks previos resuelvan
|
|
slug: enmanuel-gutierrez-perez
|
|
sexo: hombre # hombre|mujer|null
|
|
fecha_nacimiento: 1997-03-05 # ISO o null
|
|
dni: 54370345R # o null
|
|
direccion: "Calle Eugenia Rios 14, 29718 Almachar, Malaga" # texto plano, no wikilink
|
|
pais: españa
|
|
tags: [persona, osint]
|
|
fuente: "NotasDeObsidian/personas/Enmanuel Gutierrez Perez.md" # origen de la extracción
|
|
```
|
|
|
|
Body, secciones en este orden (omitir las vacías):
|
|
|
|
```markdown
|
|
## Documentos
|
|
- [[enmanuel-gutierrez-perez/dni|DNI]]
|
|
- [[enmanuel-gutierrez-perez/certificado-digital|Certificado digital]]
|
|
|
|
## Relaciones
|
|
- [[manuel-gutierrez-gamez|Manuel Gutierrez Gamez]] — hermano
|
|
|
|
## Notas
|
|
Texto libre de investigación.
|
|
```
|
|
|
|
## 3b. Esquema canónico del frontmatter de persona
|
|
|
|
Todas las fichas `personas/<slug>.md` comparten el mismo conjunto de campos, en este orden.
|
|
Campos sin valor se dejan como `null` (o `[]` para listas) — nunca se omiten, para que el
|
|
cálculo de datapoints y el score de completitud sean consistentes.
|
|
|
|
```yaml
|
|
tipo: persona
|
|
nombre: "Nombre Apellidos"
|
|
slug: nombre-apellidos
|
|
aliases: [] # otros nombres por los que aparece
|
|
sexo: null # hombre | mujer | null
|
|
fecha_nacimiento: null # ISO YYYY-MM-DD | null
|
|
dni: null
|
|
telefono: null
|
|
email: null
|
|
direccion: null # texto plano
|
|
pais: null
|
|
relaciones: [] # ["[[slug]] — parentesco/rol"]
|
|
contexto: null # familia | aurgiobsidian | ... (origen/circulo)
|
|
fuente: "" # nota/vault de procedencia
|
|
tags: [persona, osint]
|
|
```
|
|
|
|
Campos extra heredados (p.ej. `horoscopo`) se conservan al final del frontmatter.
|
|
|
|
**Datapoints y score de fiabilidad.** Los campos de identidad que cuentan para el score de
|
|
completitud son: `sexo, fecha_nacimiento, dni, telefono, email, direccion, pais` (7). El score
|
|
de una ficha es `campos_identidad_presentes / 7 * 100`. Una ficha por debajo del 100% tiene
|
|
datapoints faltantes. El total de datapoints de una persona suma además sus documentos,
|
|
attachments y relaciones. Lo calcula `projects/osint/tools/person_datapoints.py`.
|
|
|
|
## 4. Nota-documento — `personas/<slug>/<doc-slug>.md`
|
|
|
|
Una nota-documento agrupa los attachments de un tipo de documento de la persona.
|
|
|
|
`<doc-slug>` canónico (deriva del título original quitando el nombre de la persona y
|
|
normalizando):
|
|
|
|
| Título original (ejemplos) | doc-slug | doc_tipo |
|
|
|---|---|---|
|
|
| `Dni X`, `DNI de X` | `dni` | dni |
|
|
| `Certificado Digital X` | `certificado-digital` | certificado |
|
|
| `Carnet de conducir de X`, `Documentos Carnet Conducir X` | `carnet-conducir` | carnet |
|
|
| `Fotos X`, `Fotos de X` | `fotos` | fotos |
|
|
| `Vida Laboral X` | `vida-laboral` | laboral |
|
|
| `Nominas <empresa> X` | `nominas-<empresa>` | laboral |
|
|
| `Documentos <banco> X` (Abanca, BBVA, Cajamar…) | `documentos-<banco>` | banco |
|
|
| `Modelo 100 X`, `Alta autonomo X` | `modelo-100`, `alta-autonomo` | fiscal |
|
|
| `Datos empadronamiento X` | `empadronamiento` | otro |
|
|
| `Contrato <x> X` | `contrato-<x>` | contrato |
|
|
| (sin patrón claro) | slug del título sin el nombre | otro |
|
|
|
|
Frontmatter:
|
|
|
|
```yaml
|
|
tipo: documento
|
|
doc_tipo: dni # dni|certificado|carnet|fotos|banco|fiscal|laboral|contrato|otro
|
|
persona: "[[enmanuel-gutierrez-perez]]"
|
|
fuente: "NotasDeObsidian/Dni Enmanuel Gutierrez.md"
|
|
```
|
|
|
|
Body: los embeds reescritos a la ruta de attachments de la persona:
|
|
|
|
```markdown
|
|
![[attachments/personas/enmanuel-gutierrez-perez/dni-1.jpg]]
|
|
![[attachments/personas/enmanuel-gutierrez-perez/dni-2.jpeg]]
|
|
```
|
|
|
|
## 5. Attachments — `attachments/personas/<slug>/`
|
|
|
|
- Cada binario referenciado por una nota-documento se mueve a `attachments/personas/<slug>/`.
|
|
- Se renombra a `<doc-slug>-NN.<ext>` (1-indexed, en el orden en que aparece en la nota),
|
|
preservando la extensión original en minúsculas. Ej: `dni-1.jpg`, `dni-2.jpeg`,
|
|
`documentos-abanca-1.pdf`.
|
|
- Si el nombre original es relevante, se anota en el body de la nota-documento como comentario.
|
|
|
|
## 6. Entidades que NO son personas
|
|
|
|
Notas como `FenixFood SL`, `Documento Endesa`, `Documentos Aduanas …` van a `organizaciones/`;
|
|
las direcciones/lugares (`Calle Eugenia Rios …`) van a `lugares/`. Ambas carpetas siguen el
|
|
mismo patrón que `personas/`: `<slug>.md` como ficha + subcarpeta `<slug>/` para sus
|
|
documentos + `attachments/<organizaciones|lugares>/<slug>/` para sus binarios. El frontmatter
|
|
usa `tipo: organizacion` / `tipo: lugar` en vez de `tipo: persona`.
|
|
|
|
## 7. Relaciones y direcciones
|
|
|
|
- **Relaciones** entre personas (`Hermano de [[X]]`) se normalizan a la sección `## Relaciones`
|
|
de la ficha, enlazando al `slug` de la otra persona con alias legible.
|
|
- **Direcciones**: en el frontmatter `direccion` como texto plano (no wikilink). Si una dirección
|
|
es entidad de investigación propia, tiene además su ficha en `lugares/<slug>.md`, y la persona
|
|
la enlaza con `direccion: "[[lugares/<slug>|texto legible]]"` si se quiere navegable.
|
|
|
|
## 8. Idempotencia de la extracción
|
|
|
|
El migrador debe ser re-ejecutable: si una persona ya existe en osint con su slug, se
|
|
actualiza (no se duplica). Los attachments ya movidos no se vuelven a mover.
|
|
|
|
## 9. Scans de red (recon)
|
|
|
|
Todo escaneo de red de una investigación —WHOIS, RDAP, DNS, nmap, traceroute, ping— se
|
|
**archiva SIEMPRE en OSINT**. No existen scans sueltos: el resultado queda como nota navegable
|
|
en el vault y como fila consultable en la base de datos. Lo gestionan las funciones del grupo
|
|
de capacidad `recon` del registry (dominio `cybersecurity`); ver `docs/capabilities/recon.md`.
|
|
|
|
### 9.1 Nota del scan en el vault
|
|
|
|
Cada scan produce una nota Markdown bajo la carpeta del dominio escaneado:
|
|
|
|
```
|
|
dominios/<slug>/recon/<scan_type>-<YYYYMMDD-HHMM>.md
|
|
```
|
|
|
|
donde `<scan_type>` es uno de `whois | rdap | dns | nmap | traceroute | ping` y el timestamp
|
|
tiene granularidad de minuto. Frontmatter de la nota:
|
|
|
|
```yaml
|
|
tipo: scan-red
|
|
scan_tipo: whois # whois|rdap|dns|nmap|traceroute|ping
|
|
target: "ejemplo.com" # objetivo original (dominio, host o IP)
|
|
slug: ejemplo.com # slug del target (clave de la carpeta)
|
|
fecha: 2026-06-14T13:18:00 # ISO, momento del scan
|
|
herramienta: whois # CLI usada (whois, dig, nmap, ...)
|
|
tags: [scan-red, whois, recon]
|
|
```
|
|
|
|
Body: cabecera con target/tipo/herramienta/fecha, un `## Resumen` opcional con los campos
|
|
destacados del scan, y la salida cruda completa (`raw`) dentro de un bloque de código. La nota
|
|
es la **capa crítica**: si no se puede escribir, el guardado falla.
|
|
|
|
### 9.2 Tabla `network_scans` (DuckDB, service osint_db)
|
|
|
|
Además de la nota, cada scan se registra en la tabla `network_scans` (schema `main`) de la
|
|
base DuckDB que posee el service `osint_db` (single-writer), vía
|
|
`POST http://127.0.0.1:8771/api/scan`. Columnas:
|
|
|
|
| Columna | Qué |
|
|
|---|---|
|
|
| `id` | Identificador del scan |
|
|
| `target` | Objetivo original (dominio/host/IP) |
|
|
| `target_slug` | Slug del target (clave de agrupación) |
|
|
| `scan_type` | `whois \| rdap \| dns \| nmap \| traceroute \| ping` |
|
|
| `tool` | CLI usada (whois, dig, nmap, ...) |
|
|
| `scan_ts` | Timestamp ISO del scan |
|
|
| `note_path` | Ruta relativa de la nota en el vault |
|
|
| `summary` | JSON con los campos resumidos del scan |
|
|
| `created_at` | Timestamp de inserción |
|
|
|
|
Es la **capa best-effort**: si `osint_db` está caído o no expone el endpoint, el guardado
|
|
degrada a solo-nota (`registered=False` + aviso) sin fallar. El re-ingest del vault NO borra
|
|
`network_scans` —es una tabla de datos vivos, no derivada de las notas.
|
|
|
|
### 9.3 Cómo lanzar y guardar
|
|
|
|
El camino canónico es el pipeline one-shot del registry, que escanea y archiva en una sola
|
|
llamada:
|
|
|
|
```bash
|
|
cd /home/enmanuel/fn_registry
|
|
./fn run recon_osint <target> <scan_type> # p.ej. ./fn run recon_osint ejemplo.com whois
|
|
```
|
|
|
|
Para un nmap pesado (full-tcp, vuln, udp-top) lanzar en segundo plano por la duración:
|
|
|
|
```bash
|
|
nohup ./fn run recon_osint scanme.nmap.org nmap --profile full-tcp --timeout-s 7200 \
|
|
> /tmp/recon-fulltcp.log 2>&1 &
|
|
```
|
|
|
|
Alternativa atómica (controlas el scan y lo guardas aparte) desde Python, importando las
|
|
funciones del registry —no se reescriben:
|
|
|
|
```python
|
|
import sys; sys.path.insert(0, "python/functions")
|
|
from cybersecurity import dns_records
|
|
from cybersecurity.save_scan_to_osint import save_scan_to_osint
|
|
|
|
scan = dns_records("ejemplo.com")
|
|
if scan["status"] == "ok":
|
|
save_scan_to_osint("ejemplo.com", "dns", scan["raw"],
|
|
summary={"A": scan["records"].get("A")}, tool="dig")
|
|
```
|
|
|
|
### 9.4 Cómo consultar scans guardados
|
|
|
|
Desde una nota del vault, con un bloque `osintdb` (plugin osint-db) que consulta la tabla:
|
|
|
|
````markdown
|
|
```osintdb
|
|
SELECT scan_type, tool, scan_ts, note_path
|
|
FROM network_scans
|
|
WHERE target_slug = 'ejemplo.com'
|
|
ORDER BY scan_ts DESC
|
|
```
|
|
````
|
|
|
|
O contra el service directamente vía `/api/query` (mismo SQL). El slug del target se deriva
|
|
igual que en todo el vault:
|
|
|
|
```python
|
|
import re
|
|
slug = re.sub(r"[^a-z0-9._-]+", "-", target.lower())
|
|
```
|
|
|
|
> Nota: el `slug` de un dominio/host (p.ej. `ejemplo.com`, `192.168.1.10`) conserva puntos y
|
|
> guiones porque el set permitido es `[a-z0-9._-]`; difiere del slug de persona de la sección 2,
|
|
> que solo admite `[a-z0-9-]`.
|