63f37257cd
F1 — migraciones: 002_multivalue (persons +telefonos/emails/direcciones/extra_fm JSON,
backfill desde singulares con to_json) + 003_addressbooks (tabla addressbooks + seed
idempotente de la libreta por defecto). Conteos intactos (697/1065/98).
F2 — ingest_vault selectivo (anti-pisado): personas que ya existen en DB solo actualizan
note_path + extra_fm vía duckdb_upsert(update_cols=...), NO pisan los campos OWNED por la
DB; personas nuevas = bootstrap completo. _link_contacts enlaza por listas telefonos[]/
emails[] además del singular. ingest_dav itera todas las libretas de la tabla addressbooks.
F3 — escritura estructurada (server/writes.py + endpoints en main.py): CRUD
/api/person|contact|event, /api/addressbook, /api/calendar, /api/person/{slug}/render
(DB→nota preservando la prosa del cuerpo), /api/push/dav (reconcilia DB→Xandikos). El push
DAV y el render ocurren fuera de la transacción de escritura para no bloquear la DB con
latencia de red. registry_bridge.py importa las funciones nuevas; app.md actualizado.
Verificado: 18 tests verdes; ownership probado sobre datos reales (un centinela DB-owned
sobrevivió a POST /api/ingest/vault sobre las 697 fichas); person CRUD + materialización
de la ficha .md en vivo, con cleanup sin residuo.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
27 lines
1.6 KiB
SQL
27 lines
1.6 KiB
SQL
-- Migración 002: campos multi-valor en persons + frontmatter no-owned.
|
|
--
|
|
-- La inversión "DuckDB como fuente de verdad" hace que las fichas de persona
|
|
-- puedan tener varios teléfonos, emails y direcciones (no solo el singular del
|
|
-- frontmatter). Se añaden columnas JSON con la lista completa y se mantienen las
|
|
-- columnas singulares (telefono/email/direccion) por compatibilidad: el service
|
|
-- las rellena con el primer elemento de cada lista al materializar la ficha.
|
|
--
|
|
-- extra_fm guarda las claves del frontmatter de la nota que NO son campos OWNED
|
|
-- de la DB ni claves de control (slug/tipo/fuente/note_path): así un re-ingest
|
|
-- del vault puede refrescarlas sin pisar lo que la DB posee.
|
|
--
|
|
-- DuckDB 1.5.3: soporta ALTER TABLE ADD COLUMN IF NOT EXISTS y to_json([...]).
|
|
-- Aditiva e idempotente.
|
|
|
|
ALTER TABLE persons ADD COLUMN IF NOT EXISTS telefonos JSON;
|
|
ALTER TABLE persons ADD COLUMN IF NOT EXISTS emails JSON;
|
|
ALTER TABLE persons ADD COLUMN IF NOT EXISTS direcciones JSON;
|
|
ALTER TABLE persons ADD COLUMN IF NOT EXISTS extra_fm JSON;
|
|
|
|
-- Backfill: deriva las listas desde los singulares existentes la primera vez.
|
|
-- COALESCE deja '[]' donde no había singular, para no dejar NULLs en las listas.
|
|
UPDATE persons SET
|
|
telefonos = CASE WHEN telefonos IS NULL AND telefono IS NOT NULL THEN to_json([telefono]) ELSE COALESCE(telefonos, '[]') END,
|
|
emails = CASE WHEN emails IS NULL AND email IS NOT NULL THEN to_json([email]) ELSE COALESCE(emails, '[]') END,
|
|
direcciones = CASE WHEN direcciones IS NULL AND direccion IS NOT NULL THEN to_json([direccion]) ELSE COALESCE(direcciones,'[]') END;
|