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>
This commit is contained in:
@@ -9,12 +9,17 @@ uses_functions:
|
||||
- build_obsidian_graph_py_obsidian
|
||||
- list_obsidian_notes_py_obsidian
|
||||
- read_obsidian_note_py_obsidian
|
||||
- create_obsidian_note_py_obsidian
|
||||
- update_obsidian_note_py_obsidian
|
||||
- delete_obsidian_note_py_obsidian
|
||||
- extract_obsidian_embeds_py_obsidian
|
||||
- resolve_obsidian_embed_py_obsidian
|
||||
- slugify_obsidian_name_py_obsidian
|
||||
- search_obsidian_notes_py_obsidian
|
||||
- dav_list_resources_py_infra
|
||||
- dav_get_resource_py_infra
|
||||
- dav_get_collection_py_infra
|
||||
- dav_collection_ctag_py_infra
|
||||
- carddav_put_vcard_py_infra
|
||||
- dav_delete_resource_py_infra
|
||||
- split_vcards_py_infra
|
||||
- pass_get_secret_py_infra
|
||||
uses_types: []
|
||||
@@ -43,11 +48,22 @@ web local:
|
||||
2. **El servidor Xandikos** (CardDAV/CalDAV): agenda de contactos y calendario de
|
||||
eventos.
|
||||
|
||||
Edición de contactos (CRUD): la app permite crear, editar y borrar contactos
|
||||
(personas y organizaciones). La **fuente de verdad es la ficha `.md` del vault**
|
||||
(esquema canónico de `CONVENTIONS.md` §3b/§6); Xandikos es el retransmisor al
|
||||
móvil. Cada alta/edición/borrado escribe primero la ficha del vault (acción
|
||||
primaria con `create_obsidian_note` / `update_obsidian_note` /
|
||||
`delete_obsidian_note`) y a continuación refleja el cambio en Xandikos de
|
||||
inmediato (`carddav_put_vcard` / `dav_delete_resource`) para que se vea ya en la
|
||||
app y en el móvil sin esperar al sync periódico del dag_engine.
|
||||
|
||||
Registry-first: el backend NO parsea el vault ni habla DAV a mano — orquesta las
|
||||
funciones del grupo `obsidian` (`build_obsidian_graph`, `read_obsidian_note`,
|
||||
`resolve_obsidian_embed`, ...) y del grupo `dav` (`dav_list_resources`,
|
||||
`dav_get_resource`, `split_vcards`) más `pass_get_secret` para la credencial,
|
||||
todas declaradas en `uses_functions`.
|
||||
`create_obsidian_note`, `update_obsidian_note`, `delete_obsidian_note`,
|
||||
`resolve_obsidian_embed`, ...) y del grupo `dav` (`dav_get_collection`,
|
||||
`dav_collection_ctag`, `carddav_put_vcard`, `dav_delete_resource`,
|
||||
`split_vcards`) más `pass_get_secret` para la credencial, todas declaradas en
|
||||
`uses_functions`.
|
||||
|
||||
## Stack
|
||||
|
||||
|
||||
Reference in New Issue
Block a user