Commit Graph

4 Commits

Author SHA1 Message Date
egutierrez 43889bfc07 feat(contacts): CRUD de contactos (vault .md fuente de verdad + reflejo vCard)
Añade alta, edición y borrado de contactos (personas y organizaciones) a la
app osint_web. La fuente de verdad es la ficha .md del vault Obsidian
(CONVENTIONS.md §3b/§6); Xandikos es el retransmisor al móvil.

Backend (server/main.py):
- POST /api/contact: genera slug, escribe la ficha .md con el frontmatter
  canónico + PUT del vCard a Xandikos. 409 si el slug ya existe.
- PUT /api/contact/{slug}: merge del frontmatter (preserva campos heredados)
  + re-PUT del vCard. 404 si no existe.
- DELETE /api/contact/{slug}: borra la ficha .md + DELETE del vCard. 404 si
  no existe.
Cada escritura invalida la caché DAV para que el cambio se vea ya en la app.
Registry-first: orquesta create/update/delete_obsidian_note del grupo obsidian
y carddav_put_vcard/dav_delete_resource del grupo dav (sin reimplementar
parseo ni HTTP). Mapea los campos OSINT a propiedades X-OSINT-* del vCard.

Frontend (ContactsView.tsx + api.ts + format.ts):
- Botón "Nuevo contacto" → modal con formulario Mantine (TextInput,
  TagsInput aliases, Select contexto, Textarea notas).
- Detalle: botones "Editar" (formulario precargado) y "Borrar" (con
  confirmación). Tras guardar refresca la lista.
- Helper slugify (replica slugify_obsidian_name) para resolver la ficha.

Tests: 6 nuevos casos (ciclo crear→editar→borrar con .md real + reflejo vCard
mockeado, organización, 404s, tipo inválido, preserva campos heredados). Suite
27 passed. Ciclo e2e real verificado contra Xandikos + vault (vCard creado,
editado y borrado; slug zz-test-crud limpiado). pnpm build verde (React 19 +
Mantine v9).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:18:55 +02:00
egutierrez 4ac8f33318 perf(dav): multiget en 1 request + cache en disco por ctag (de ~9s a ~1s)
Reemplaza el patron N+1 (PROPFIND + un GET por cada .vcf/.ics, paralelizado con
ThreadPoolExecutor pero ~9s para 1064 contactos) por UNA llamada a la funcion
del registry dav_get_collection (REPORT addressbook-query / calendar-query que
trae todo el contenido inline). Anade cache en disco (.cache/contacts.json y
calendar.json) validada por el ctag de la coleccion (dav_collection_ctag): al
arrancar, si el ctag no cambio, sirve del disco sin tocar la red. POST
/api/refresh fuerza recarga (ignora el ctag). _force_reload distingue refresh
forzado de validacion normal.

Cambios en /api/contacts y /api/calendar: el N+1 (_fetch_resources +
ThreadPoolExecutor) se sustituye por _load_collection (ctag -> disco o REPORT).
El parseo vCard/iCal y el shape JSON no cambian; los items cacheados en disco
preservan el shape completo (osint, nombre, telefonos). Tests actualizados:
fake_dav mockea dav_get_collection + dav_collection_ctag con cache en tmpdir;
nuevos tests de disk-cache-hit en proceso nuevo y recarga al cambiar ctag.

Medido contra Xandikos real: contacts 1064 cold 1.15s / warm 6ms / disco 0.5s;
calendar 98 cold 0.29s. Registry-first: la logica DAV nueva vive en el grupo dav
(dav_get_collection_py_infra + dav_collection_ctag_py_infra), no inline.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:08:02 +02:00
agent 59558d43cb perf: descarga DAV concurrente + caché de contactos/calendario
Las colecciones Xandikos son grandes (1064 contactos, 98 eventos). Descargar
los .vcf/.ics secuencialmente tardaba ~2 min para los contactos (timeout). Se
añade _fetch_resources con un ThreadPoolExecutor acotado (16 workers): primera
carga de /api/contacts baja a ~9s, segunda (cacheada) a ~10ms. La descarga
sigue delegada a dav_get_resource del registry (stdlib, thread-safe); solo se
paraleliza la orquestación.

Incluye caché en memoria de contactos y calendario (invalidada por
/api/refresh), DavUnavailable para degradación clara sin red, y campos
aliaseados en español (nombre/alias/telefonos/correos/osint) para el frontend.

Verificado contra el vault real (1199 nodos) y Xandikos real (1064 contactos,
98 eventos). 19 tests verdes.
2026-06-11 22:54:54 +02:00
agent 5b51e3d035 feat: FastAPI backend (vault osint + agenda/calendario Xandikos)
Reescribe el backend a FastAPI + uvicorn y añade los endpoints DAV
(CardDAV/CalDAV) sobre el servidor Xandikos, además de las vistas del vault
osint de Obsidian.

Vault (grupo obsidian del registry):
- /api/graph, /api/nodes, /api/node/{slug}, /api/attachment, /api/search,
  /api/refresh. Allowlist estricta de path traversal en /api/attachment.
- Resolución de embeds por path relativo al vault y por basename (registry).

Xandikos (grupo dav del registry + pass_get_secret):
- /api/contacts, /api/contact/{uid} (CardDAV, parseo vCard a JSON).
- /api/calendar?from=&to= (CalDAV, parseo VEVENT a JSON, filtro por rango).
- Credencial vía pass dav/xandikos-enmanuel; degradación clara sin red (502/503).

Solo escucha en 127.0.0.1 (datos sensibles). 13 tests verdes (pytest).
frontend/README.md describe el montaje React+Vite+Mantine+sigma.js posterior.
2026-06-11 22:47:51 +02:00