diff --git a/backlog/recall-mvp5-tickets-detallado.md b/backlog/recall-mvp5-tickets-detallado.md
new file mode 100644
index 0000000..b042c28
--- /dev/null
+++ b/backlog/recall-mvp5-tickets-detallado.md
@@ -0,0 +1,970 @@
+# Recall — Tickets técnicos MVP-5 (Confianza, flujo diario y expansión)
+
+## Objetivo general
+Consolidar Recall como sistema principal de pensamiento y memoria externa, enfocado en:
+- confianza total en los datos
+- reducción extrema de fricción
+- captura desde fuera de la app
+- recuperación y operación desde teclado
+- portabilidad real del conocimiento
+
+## Principios de producto
+1. **No perder nada**: backup y restore confiables.
+2. **Todo a mano**: acciones principales accesibles por teclado.
+3. **Captura ubicua**: guardar conocimiento desde cualquier contexto.
+4. **Salida garantizada**: exportaciones útiles y reversibles.
+5. **Experiencia continua**: la app acompaña el flujo de trabajo, no lo interrumpe.
+
+---
+
+# EPIC 1 — Confianza total y resiliencia de datos
+
+## [P1] Ticket 01 — Diseñar estrategia de backup automático local
+
+**Objetivo**
+Definir e implementar una estrategia segura de backup automático para evitar pérdida de datos y aumentar la confianza en Recall.
+
+**Contexto**
+Recall ya cuenta con export/import manual e historial de versiones por nota. El siguiente salto es garantizar respaldo periódico y silencioso del estado global del conocimiento.
+
+**Problema que resuelve**
+- Riesgo de pérdida por errores del usuario, corrupción local o cambios no deseados.
+- Dependencia de exportaciones manuales.
+- Falta de sensación de “sistema confiable”.
+
+**Alcance**
+- Diseñar estrategia de backup automático basada en eventos y/o tiempo:
+ - al detectar cambios significativos
+ - cada cierto intervalo configurable
+ - al cerrar sesión o abandonar pestaña cuando aplique
+- Definir formato del backup:
+ - JSON estructurado compatible con importación
+ - metadatos de versión, fecha, origen, conteos
+- Definir almacenamiento inicial:
+ - IndexedDB recomendado para snapshots locales
+ - alternativa: local filesystem vía descarga manual asistida
+- Crear servicio de generación de backup
+- Crear política de retención:
+ - conservar últimos N backups
+ - limpiar backups viejos automáticamente
+
+**No incluye**
+- sincronización cloud
+- backup remoto
+- cifrado extremo a extremo
+
+**Criterios de aceptación**
+- La app genera backups automáticamente sin intervención manual
+- Los backups se almacenan con timestamp y metadatos
+- Existe retención automática configurable o fija
+- El proceso no bloquea la UI
+- El formato es compatible con restore/import
+- Hay tests para serialización y política de retención
+
+**Archivos sugeridos**
+- `src/lib/backup.ts`
+- `src/lib/backup-storage.ts`
+- `src/lib/backup-policy.ts`
+- `src/types/backup.ts`
+- `src/app/settings/page.tsx`
+- `src/app/api/export-import/route.ts`
+
+**Notas técnicas**
+- Separar claramente:
+ - generación del snapshot
+ - persistencia local
+ - política de retención
+- Preferir un esquema de versión explícito del backup (`schemaVersion`)
+- Incluir checksum o hash simple opcional para detectar corrupción
+- Mantener compatibilidad hacia atrás cuando cambie el formato
+
+---
+
+## [P1] Ticket 02 — Implementar motor de snapshot global exportable
+
+**Objetivo**
+Crear una utilidad robusta que genere snapshots completos y consistentes del estado de Recall.
+
+**Alcance**
+- Incluir en el snapshot:
+ - notas
+ - tags
+ - backlinks/enlaces si corresponden
+ - métricas relevantes necesarias para restore
+ - versiones de notas, si se decide incluirlas
+ - metadatos de creación
+- Crear función `createBackupSnapshot()`
+- Reutilizar la lógica existente de exportación para evitar duplicación
+- Estandarizar el shape del payload exportable
+
+**No incluye**
+- compresión
+- cifrado
+
+**Criterios de aceptación**
+- Un snapshot puede reconstruir el estado esperado del sistema
+- El export manual y el backup automático comparten formato base o traductor explícito
+- Tests verifican consistencia del snapshot
+- El snapshot incluye versión de esquema y fecha de creación
+
+**Archivos sugeridos**
+- `src/lib/backup.ts`
+- `src/lib/export.ts`
+- `src/app/api/export-import/route.ts`
+- `__tests__/backup.test.ts`
+
+**Notas técnicas**
+- Evitar incluir datos derivados si pueden regenerarse fácilmente
+- Documentar claramente qué campos se consideran fuente de verdad
+- Si `NoteUsage` no debe restaurarse, dejarlo explícito en especificación
+
+---
+
+## [P1] Ticket 03 — Restore desde backup con preview y validación
+
+**Objetivo**
+Permitir restaurar un backup de forma segura, transparente y reversible.
+
+**Alcance**
+- Crear flujo de restore desde Settings
+- Validar el archivo antes de aplicar:
+ - schemaVersion
+ - integridad mínima
+ - estructura esperada
+- Mostrar preview:
+ - cantidad de notas
+ - tags
+ - versiones
+ - fecha del backup
+- Permitir dos modos:
+ - merge
+ - replace completo
+- Confirmación explícita antes de aplicar
+
+**No incluye**
+- merge inteligente avanzado por conflicto
+- restore parcial por selección de entidades
+
+**Criterios de aceptación**
+- El usuario puede seleccionar un backup y previsualizarlo
+- El sistema informa claramente qué se va a restaurar
+- Hay confirmación antes del replace
+- El restore fallido no deja la base en estado inconsistente
+- Existe feedback claro de éxito/error
+
+**Archivos sugeridos**
+- `src/components/backup-restore-dialog.tsx`
+- `src/lib/restore.ts`
+- `src/lib/backup-validator.ts`
+- `src/app/settings/page.tsx`
+- `src/app/api/export-import/route.ts`
+
+**Notas técnicas**
+- En `replace`, considerar transacción única
+- En `merge`, definir reglas claras por ID/título
+- Crear un backup previo automático antes de aplicar restore
+
+---
+
+## [P1] Ticket 04 — Backup previo automático antes de operaciones destructivas
+
+**Objetivo**
+Reducir al mínimo el riesgo antes de operaciones peligrosas.
+
+**Alcance**
+- Generar backup automático antes de:
+ - restore replace
+ - import replace
+ - borrados masivos futuros
+- Etiquetar ese backup como `pre-destructive`
+- Permitir revertir rápidamente
+
+**Criterios de aceptación**
+- Antes de una operación destructiva se crea un backup
+- El backup queda identificado y visible en UI
+- Si la operación falla, el backup sigue disponible
+
+**Archivos sugeridos**
+- `src/lib/backup.ts`
+- `src/lib/restore.ts`
+- `src/app/settings/page.tsx`
+
+---
+
+## [P1] Ticket 05 — Guard de cambios no guardados
+
+**Objetivo**
+Evitar pérdida accidental de trabajo durante edición.
+
+**Alcance**
+- Detectar cambios sucios en `note-form`
+- Advertir al:
+ - navegar fuera de la página
+ - cerrar pestaña
+ - refrescar
+- Permitir omitir warning cuando no hay cambios
+
+**No incluye**
+- autosave completo
+- borradores persistentes
+
+**Criterios de aceptación**
+- Si hay cambios sin guardar, aparece advertencia al salir
+- Si no hay cambios, no aparece advertencia
+- Funciona en crear y editar
+- No rompe submit exitoso
+
+**Archivos sugeridos**
+- `src/hooks/use-unsaved-changes.ts`
+- `src/components/note-form.tsx`
+- `src/app/edit/[id]/page.tsx`
+- `src/app/new/page.tsx`
+
+**Notas técnicas**
+- Diferenciar estado inicial vs actual
+- Manejar `beforeunload` con cuidado por compatibilidad del navegador
+
+---
+
+## [P2] Ticket 06 — Autosave opcional de borrador local
+
+**Objetivo**
+Agregar una capa extra de protección sin imponer complejidad excesiva.
+
+**Alcance**
+- Guardar borrador local temporal de la nota en edición
+- Recuperarlo al reabrir la pantalla
+- Permitir descartarlo manualmente
+
+**Criterios de aceptación**
+- Si se cierra accidentalmente, el borrador puede recuperarse
+- El borrador se limpia al guardar correctamente
+- El usuario puede descartar borrador recuperado
+
+**Archivos sugeridos**
+- `src/lib/drafts.ts`
+- `src/components/note-form.tsx`
+- `src/components/draft-recovery-banner.tsx`
+
+---
+
+# EPIC 2 — Operación diaria desde teclado
+
+## [P1] Ticket 07 — Command Palette global (`Ctrl+K` / `Cmd+K`)
+
+**Objetivo**
+Centralizar búsqueda, navegación y acciones en una interfaz rápida tipo command palette.
+
+**Contexto**
+Recall ya tiene búsqueda potente y navegación por teclado en el search bar. El siguiente paso es ofrecer una capa global de comandos que reduzca aún más la fricción.
+
+**Alcance**
+- Atajo global:
+ - `Ctrl+K` en Windows/Linux
+ - `Cmd+K` en macOS
+- Modal o palette flotante global
+- Soportar acciones iniciales:
+ - buscar notas
+ - abrir nota
+ - crear nueva nota
+ - quick add
+ - ir a dashboard
+ - ir a settings
+ - ir a notas favoritas
+ - ir a notas recientes
+- Secciones:
+ - acciones
+ - resultados de búsqueda
+ - navegación
+- Navegación total por teclado
+
+**No incluye**
+- edición avanzada dentro de la palette
+- plugins de comandos externos
+
+**Criterios de aceptación**
+- La palette abre/cierra con shortcut global
+- Se puede usar sin mouse
+- Enter ejecuta acción seleccionada
+- ESC cierra
+- Resultados y acciones están claramente separadas
+- Funciona desde cualquier pantalla
+
+**Archivos sugeridos**
+- `src/components/command-palette.tsx`
+- `src/hooks/use-command-palette.ts`
+- `src/lib/command-palette.ts`
+- `src/app/layout.tsx`
+- `src/components/header.tsx`
+
+**Notas técnicas**
+- Reutilizar `search.ts` y la API existente cuando sea posible
+- Mantener selección activa y scroll automático
+- Considerar accesibilidad: focus trap, ARIA roles
+
+---
+
+## [P1] Ticket 08 — Modelo de acciones y proveedores para Command Palette
+
+**Objetivo**
+Desacoplar la palette de las acciones concretas para facilitar expansión futura.
+
+**Alcance**
+- Crear modelo uniforme de comando:
+ - id
+ - label
+ - description
+ - group
+ - keywords
+ - action handler
+ - icon opcional
+- Crear proveedores:
+ - acciones estáticas
+ - notas recientes
+ - resultados de búsqueda
+- Sistema de ranking simple para comandos
+
+**Criterios de aceptación**
+- Se pueden agregar nuevas acciones sin tocar el core visual
+- La palette consume una lista homogénea de items
+- El sistema soporta agrupación y orden
+
+**Archivos sugeridos**
+- `src/lib/command-items.ts`
+- `src/lib/command-groups.ts`
+- `src/lib/command-ranking.ts`
+- `src/components/command-palette.tsx`
+
+---
+
+## [P1] Ticket 09 — Acciones rápidas por teclado fuera de la palette
+
+**Objetivo**
+Expandir la operación de Recall sin depender de clicks.
+
+**Alcance**
+- Definir shortcuts globales seguros:
+ - `g h` → dashboard
+ - `g n` → notas
+ - `n` → nueva nota
+ - `/` → enfocar búsqueda
+ - `?` → ayuda de shortcuts
+- Mostrar ayuda contextual de shortcuts
+
+**Criterios de aceptación**
+- Los shortcuts no interfieren con inputs activos
+- Se pueden desactivar en campos de texto
+- Existe una vista/modal de ayuda
+
+**Archivos sugeridos**
+- `src/hooks/use-global-shortcuts.ts`
+- `src/components/keyboard-shortcuts-dialog.tsx`
+- `src/app/layout.tsx`
+
+**Notas técnicas**
+- Ignorar shortcuts cuando hay foco en input, textarea o contenteditable
+- Centralizar mapa de shortcuts en un único archivo
+
+---
+
+## [P2] Ticket 10 — Navegación completa de listas por teclado
+
+**Objetivo**
+Permitir abrir y operar notas desde listados sin usar mouse.
+
+**Alcance**
+- Flechas para moverse entre resultados/listas
+- Enter para abrir
+- Atajos para:
+ - editar
+ - favorite
+ - pin
+- Soporte en:
+ - `/notes`
+ - dashboard
+ - dropdown de búsqueda
+
+**Criterios de aceptación**
+- Las listas principales se pueden recorrer por teclado
+- El elemento seleccionado tiene estado visual claro
+- Las acciones rápidas no rompen accesibilidad
+
+**Archivos sugeridos**
+- `src/components/note-list.tsx`
+- `src/components/dashboard.tsx`
+- `src/components/search-bar.tsx`
+
+---
+
+# EPIC 3 — Contexto activo y workspace continuo
+
+## [P1] Ticket 11 — Sidebar contextual persistente mejorada
+
+**Objetivo**
+Convertir la sidebar contextual en un asistente permanente del flujo de trabajo.
+
+**Alcance**
+- Mantener sidebar visible en detalle de nota y opcionalmente en edición
+- Secciones posibles:
+ - relacionadas
+ - backlinks
+ - co-usadas
+ - recientes
+ - versiones recientes
+ - sugerencias contextuales
+- Mejorar densidad y jerarquía visual
+- Permitir colapsar/expandir secciones
+
+**Criterios de aceptación**
+- La sidebar muestra contenido útil sin saturar
+- Las secciones pueden plegarse
+- En pantallas pequeñas se adapta sin romper el layout
+- Se distinguen claramente los tipos de relación
+
+**Archivos sugeridos**
+- `src/components/note-context-sidebar.tsx`
+- `src/components/note-connections.tsx`
+- `src/app/notes/[id]/page.tsx`
+
+---
+
+## [P2] Ticket 12 — Modo trabajo enfocado
+
+**Objetivo**
+Ofrecer una experiencia de lectura/consulta prolongada con menos distracciones y más contexto útil.
+
+**Alcance**
+- Crear un “modo trabajo” activable por toggle
+- Cambios de UI:
+ - ancho de lectura optimizado
+ - sidebar contextual persistente
+ - header reducido
+ - acciones rápidas siempre visibles
+- Persistir preferencia local
+
+**Criterios de aceptación**
+- El usuario puede activar/desactivar el modo trabajo
+- La preferencia se mantiene entre sesiones
+- Mejora la experiencia en detalle de nota sin romper navegación general
+
+**Archivos sugeridos**
+- `src/components/work-mode-toggle.tsx`
+- `src/lib/work-mode.ts`
+- `src/app/notes/[id]/page.tsx`
+- `src/app/globals.css`
+
+---
+
+## [P2] Ticket 13 — Historial de navegación contextual
+
+**Objetivo**
+Facilitar volver sobre el camino mental reciente.
+
+**Alcance**
+- Registrar secuencia reciente de notas abiertas
+- Mostrar “visto recientemente en este contexto”
+- Posibilidad de volver rápido a 5–10 notas recientes
+
+**Criterios de aceptación**
+- El usuario ve un historial local reciente
+- Puede reabrir notas anteriores con un click o atajo
+- El historial no duplica entradas consecutivas idénticas
+
+**Archivos sugeridos**
+- `src/lib/navigation-history.ts`
+- `src/components/recent-context-list.tsx`
+- `src/components/command-palette.tsx`
+- `src/components/note-context-sidebar.tsx`
+
+---
+
+# EPIC 4 — Captura ubicua fuera de Recall
+
+## [P1] Ticket 14 — Bookmarklet para guardar página actual
+
+**Objetivo**
+Permitir capturar contenido desde cualquier web hacia Recall con fricción mínima.
+
+**Contexto**
+Recall ya resuelve bien captura interna. El siguiente paso de uso diario es capturar desde el navegador sin tener que abrir manualmente la app y crear una nota.
+
+**Alcance**
+- Diseñar bookmarklet inicial que:
+ - tome `document.title`
+ - tome `location.href`
+ - opcionalmente tome selección de texto
+ - abra una URL de Recall con payload prellenado
+- Crear pantalla o endpoint receptor para captura externa
+- Mapear captura a tipo de nota por defecto (`note` o `snippet` según caso)
+
+**No incluye**
+- extensión completa de navegador
+- scraping profundo del DOM
+
+**Criterios de aceptación**
+- El bookmarklet funciona en páginas comunes
+- Si hay texto seleccionado, se incluye en la captura
+- Si no hay selección, se guarda al menos título + URL
+- Recall recibe y prellena una nota lista para confirmar o guardar
+
+**Archivos sugeridos**
+- `src/app/capture/page.tsx`
+- `src/lib/external-capture.ts`
+- `src/components/bookmarklet-instructions.tsx`
+- `src/app/settings/page.tsx`
+
+**Notas técnicas**
+- Codificar payload en query string de forma segura
+- Considerar límites de longitud: si es largo, usar mecanismo de POST o fallback
+- Sanitizar el contenido recibido
+
+---
+
+## [P1] Ticket 15 — Flujo de confirmación para captura externa
+
+**Objetivo**
+Evitar guardar basura y dar control antes de persistir.
+
+**Alcance**
+- Pantalla de revisión para captura externa:
+ - título
+ - url
+ - contenido/selección
+ - tags sugeridos
+ - tipo sugerido
+- Botones:
+ - guardar
+ - editar
+ - cancelar
+- Posibilidad de convertir la URL en markdown limpio
+
+**Criterios de aceptación**
+- La captura externa llega prellenada
+- El usuario puede corregir antes de guardar
+- El flujo es rápido y no requiere pasos innecesarios
+
+**Archivos sugeridos**
+- `src/app/capture/page.tsx`
+- `src/components/external-capture-form.tsx`
+- `src/lib/type-inference.ts`
+- `src/lib/tags.ts`
+
+---
+
+## [P2] Ticket 16 — Endpoint seguro para captura externa por POST
+
+**Objetivo**
+Preparar Recall para integraciones futuras más robustas que el bookmarklet simple.
+
+**Alcance**
+- Crear endpoint dedicado para captura externa
+- Aceptar payload estructurado:
+ - title
+ - url
+ - selection
+ - source
+ - inferredType
+- Validar con Zod
+- Responder con payload listo para preview o guardado
+
+**Criterios de aceptación**
+- El endpoint valida correctamente el payload
+- No guarda automáticamente sin intención explícita
+- Puede ser reutilizado por extensión futura o integraciones
+
+**Archivos sugeridos**
+- `src/app/api/capture/route.ts`
+- `src/lib/external-capture.ts`
+- `src/lib/validators.ts`
+
+---
+
+# EPIC 5 — Importación y exportación de nivel producto
+
+## [P1] Ticket 17 — Exportación mejorada a Markdown
+
+**Objetivo**
+Asegurar portabilidad real del conocimiento en un formato simple y durable.
+
+**Alcance**
+- Exportar todas las notas a estructura Markdown
+- Incluir:
+ - frontmatter opcional
+ - título
+ - contenido
+ - tags
+ - tipo
+ - fechas
+- Generar nombres de archivo estables y seguros
+- Opción de exportar zip de múltiples `.md`
+
+**No incluye**
+- sync con repos remotos
+- assets binarios complejos
+
+**Criterios de aceptación**
+- El usuario puede exportar todas las notas a `.md`
+- Cada nota queda representada de forma legible
+- Los archivos son reimportables con reglas definidas
+- Tags y tipo no se pierden
+
+**Archivos sugeridos**
+- `src/lib/export-markdown.ts`
+- `src/app/api/export-import/route.ts`
+- `src/app/settings/page.tsx`
+
+**Notas técnicas**
+- Resolver colisiones de nombres
+- Normalizar saltos de línea
+- Documentar formato de frontmatter si se usa
+
+---
+
+## [P1] Ticket 18 — Exportación HTML simple y legible
+
+**Objetivo**
+Facilitar compartir o archivar notas en un formato visualmente cómodo.
+
+**Alcance**
+- Crear export HTML por nota o lote
+- Incluir render de markdown
+- Estilo básico embebido o plantilla simple
+
+**Criterios de aceptación**
+- La exportación HTML es legible offline
+- Respeta headings, listas, código y enlaces
+- Puede abrirse directamente en navegador
+
+**Archivos sugeridos**
+- `src/lib/export-html.ts`
+- `src/app/api/export-import/route.ts`
+
+---
+
+## [P2] Ticket 19 — Importador de Markdown mejorado
+
+**Objetivo**
+Hacer Recall más interoperable con flujos existentes.
+
+**Alcance**
+- Mejorar importador `.md` actual para soportar:
+ - frontmatter
+ - tags
+ - tipo
+ - títulos ausentes o derivados
+ - sintaxis `[[wiki]]`
+- Permitir importar múltiples archivos si la UX lo permite
+
+**Criterios de aceptación**
+- Markdown con frontmatter se importa correctamente
+- Se preservan tags y tipo cuando existen
+- El contenido sigue siendo fiel al original
+
+**Archivos sugeridos**
+- `src/lib/import-markdown.ts`
+- `src/app/api/export-import/route.ts`
+- `src/components/import-dialog.tsx`
+
+---
+
+## [P2] Ticket 20 — Importador base de Obsidian-compatible Markdown
+
+**Objetivo**
+Reducir fricción de entrada para usuarios con conocimiento ya almacenado fuera de Recall.
+
+**Alcance**
+- Aceptar archivos/estructura compatibles con vault simple:
+ - markdown
+ - `[[wiki links]]`
+ - tags inline `#tag`
+- Resolver títulos desde filename cuando haga falta
+- Crear estrategia básica de deduplicación
+
+**Criterios de aceptación**
+- Un conjunto simple de notas estilo Obsidian se importa sin perder estructura esencial
+- Los wiki links se preservan o transforman correctamente
+- La deduplicación evita duplicados obvios
+
+**Archivos sugeridos**
+- `src/lib/import-obsidian.ts`
+- `src/app/api/export-import/route.ts`
+
+---
+
+# EPIC 6 — Operación y configuración visible
+
+## [P2] Ticket 21 — Centro de respaldo y portabilidad en Settings
+
+**Objetivo**
+Reunir en una sola UI todas las capacidades de backup, restore, import y export.
+
+**Alcance**
+- Crear sección clara en Settings:
+ - backups automáticos
+ - backups disponibles
+ - restore
+ - export JSON
+ - export Markdown
+ - export HTML
+ - import Markdown/JSON
+- Mostrar último backup realizado
+- Mostrar tamaño aproximado y fecha
+
+**Criterios de aceptación**
+- Settings concentra todas las acciones de seguridad y portabilidad
+- El usuario entiende claramente qué hace cada opción
+- El flujo no requiere conocer detalles técnicos internos
+
+**Archivos sugeridos**
+- `src/app/settings/page.tsx`
+- `src/components/backup-center.tsx`
+- `src/components/export-options.tsx`
+- `src/components/import-options.tsx`
+
+---
+
+## [P2] Ticket 22 — Configuración visible de feature flags y preferencias clave
+
+**Objetivo**
+Dar control operativo sobre comportamientos avanzados ya implementados.
+
+**Alcance**
+- Exponer desde Settings:
+ - feature flags activas
+ - modo trabajo
+ - backup automático on/off
+ - retención de backups
+ - shortcuts visibles
+- Persistencia local o en configuración simple
+
+**Criterios de aceptación**
+- El usuario puede ver y cambiar flags/preferencias principales
+- Los cambios se reflejan sin romper la app
+- Existe estado inicial razonable por defecto
+
+**Archivos sugeridos**
+- `src/app/settings/page.tsx`
+- `src/lib/features.ts`
+- `src/lib/preferences.ts`
+
+---
+
+# EPIC 7 — Calidad, seguridad operativa y pruebas
+
+## [P1] Ticket 23 — Tests unitarios para backup/restore
+
+**Objetivo**
+Proteger la capa de confianza antes de expandir más el producto.
+
+**Alcance**
+- Tests para:
+ - snapshot generation
+ - validación de backup
+ - retención
+ - restore merge
+ - restore replace
+ - backup pre-destructive
+
+**Criterios de aceptación**
+- Casos felices y bordes cubiertos
+- Fixtures de backup versionados
+- Restore inválido falla de forma segura
+
+**Archivos sugeridos**
+- `__tests__/backup.test.ts`
+- `__tests__/restore.test.ts`
+- `__tests__/backup-validator.test.ts`
+
+---
+
+## [P1] Ticket 24 — Tests de integración para command palette y captura externa
+
+**Objetivo**
+Validar los nuevos flujos de uso diario y expansión.
+
+**Alcance**
+- Probar:
+ - apertura/cierre de palette
+ - navegación por teclado
+ - ejecución de comandos
+ - recepción de captura externa
+ - flujo de confirmación de captura
+
+**Criterios de aceptación**
+- Los flujos críticos están cubiertos
+- Los shortcuts no interfieren con formularios
+- La captura externa llega correctamente prellenada
+
+**Archivos sugeridos**
+- `__tests__/command-palette.test.tsx`
+- `__tests__/capture-flow.test.tsx`
+
+---
+
+## [P2] Ticket 25 — Harden de validaciones y límites operativos
+
+**Objetivo**
+Aumentar robustez de las nuevas entradas/salidas del sistema.
+
+**Alcance**
+- Definir límites razonables para:
+ - tamaño de backup
+ - tamaño de payload de captura externa
+ - cantidad de backups retenidos
+- Validación estricta de formatos
+- Mensajes de error claros y recuperables
+
+**Criterios de aceptación**
+- El sistema rechaza entradas excesivas o inválidas de forma clara
+- No se degrada la app por payloads grandes o malformados
+- Los errores se muestran de forma consistente
+
+**Archivos sugeridos**
+- `src/lib/backup-validator.ts`
+- `src/lib/external-capture.ts`
+- `src/lib/errors.ts`
+- `src/lib/validators.ts`
+
+---
+
+# Orden recomendado de implementación
+
+## Sprint 1 — Confianza primero
+- Ticket 01 — Estrategia de backup automático local
+- Ticket 02 — Motor de snapshot global exportable
+- Ticket 03 — Restore con preview y validación
+- Ticket 04 — Backup previo automático
+- Ticket 23 — Tests unitarios backup/restore
+
+## Sprint 2 — Flujo diario brutal
+- Ticket 07 — Command Palette global
+- Ticket 08 — Modelo de acciones para palette
+- Ticket 09 — Shortcuts globales
+- Ticket 10 — Navegación de listas por teclado
+- Ticket 24 — Tests integración palette
+
+## Sprint 3 — Contexto y continuidad
+- Ticket 11 — Sidebar contextual persistente mejorada
+- Ticket 12 — Modo trabajo enfocado
+- Ticket 13 — Historial de navegación contextual
+- Ticket 05 — Guard de cambios no guardados
+- Ticket 06 — Autosave opcional de borrador local
+
+## Sprint 4 — Captura externa
+- Ticket 14 — Bookmarklet para guardar página actual
+- Ticket 15 — Flujo de confirmación para captura externa
+- Ticket 16 — Endpoint seguro para captura externa
+
+## Sprint 5 — Portabilidad real
+- Ticket 17 — Exportación mejorada a Markdown
+- Ticket 18 — Exportación HTML
+- Ticket 19 — Importador Markdown mejorado
+- Ticket 20 — Importador base Obsidian-compatible
+- Ticket 21 — Centro de respaldo y portabilidad
+- Ticket 22 — Configuración visible de flags/preferencias
+- Ticket 25 — Harden de validaciones y límites
+
+---
+
+# Dependencias y decisiones de arquitectura recomendadas
+
+## Decisión 1 — Backup format
+Definir explícitamente un formato versionado:
+
+```ts
+type RecallBackup = {
+ schemaVersion: "1.0";
+ createdAt: string;
+ source: "automatic" | "manual" | "pre-destructive";
+ appVersion?: string;
+ metadata: {
+ noteCount: number;
+ tagCount: number;
+ versionCount?: number;
+ };
+ data: {
+ notes: unknown[];
+ tags: unknown[];
+ noteVersions?: unknown[];
+ backlinks?: unknown[];
+ };
+};
+```
+
+## Decisión 2 — Restore modes
+Mantener solo dos modos al inicio:
+- `merge`: agrega/actualiza sin borrar todo
+- `replace`: reemplaza completamente el dataset
+
+No agregar modos intermedios hasta tener uso real.
+
+## Decisión 3 — Command palette scope inicial
+La primera versión debe centrarse en:
+- navegación
+- búsqueda
+- creación
+- acceso a pantallas
+No convertirla aún en un motor de automatizaciones complejas.
+
+## Decisión 4 — Bookmarklet MVP
+El bookmarklet debe ser lo más simple posible:
+- capturar `title`
+- capturar `url`
+- capturar selección si existe
+- abrir Recall con preview prellenada
+
+No hacer scraping complejo en esta fase.
+
+## Decisión 5 — Export portability
+Markdown debe convertirse en el formato de salida principal legible por humanos.
+JSON debe seguir siendo el formato fiel para restore exacto.
+
+---
+
+# Plantilla sugerida para Claude Code
+
+## Título
+`[P1] Implementar restore desde backup con preview y validación`
+
+## Contexto
+Recall ya ofrece export/import manual e historial de versiones. Para convertirlo en una herramienta confiable de uso diario, se necesita restore seguro desde backups automáticos y manuales.
+
+## Objetivo
+Permitir restaurar backups con validación previa, preview del contenido y confirmación explícita, soportando modos `merge` y `replace`.
+
+## Alcance
+- validador de backup
+- preview de metadatos
+- flujo de confirmación
+- ejecución segura del restore
+- integración con settings
+
+## No incluye
+- resolución avanzada de conflictos
+- restore parcial por tipo de entidad
+- sync remoto
+
+## Criterios de aceptación
+- ...
+- ...
+- ...
+
+## Archivos a tocar
+- ...
+- ...
+
+## Notas técnicas
+- usar transacciones en replace
+- crear backup previo automático
+- mostrar errores consistentes
+
+---
+
+# Definition of Done
+
+- Funcionalidad implementada y usable
+- Tests unitarios e integración relevantes pasando
+- Sin regresiones en CRUD, búsqueda, versiones y captura
+- Estados vacíos, borde y error cubiertos
+- UI clara para acciones sensibles
+- Portabilidad comprobable con export/import real
diff --git a/src/app/api/export-import/route.ts b/src/app/api/export-import/route.ts
index a8b723d..4bd7d68 100644
--- a/src/app/api/export-import/route.ts
+++ b/src/app/api/export-import/route.ts
@@ -3,9 +3,18 @@ import { prisma } from '@/lib/prisma'
import { noteSchema, NoteInput } from '@/lib/validators'
import { createErrorResponse, createSuccessResponse, ValidationError } from '@/lib/errors'
import { syncBacklinks } from '@/lib/backlinks'
+import { createBackupSnapshot } from '@/lib/backup'
-export async function GET() {
+export async function GET(req: NextRequest) {
try {
+ const { searchParams } = new URL(req.url)
+ const format = searchParams.get('format')
+
+ if (format === 'backup') {
+ const backup = await createBackupSnapshot('manual')
+ return createSuccessResponse(backup)
+ }
+
const notes = await prisma.note.findMany({
include: { tags: { include: { tag: true } } },
})
diff --git a/src/app/settings/page.tsx b/src/app/settings/page.tsx
index ef24481..ffff494 100644
--- a/src/app/settings/page.tsx
+++ b/src/app/settings/page.tsx
@@ -1,10 +1,11 @@
'use client'
import { useState, useRef } from 'react'
-import { Download, Upload } from 'lucide-react'
+import { Download, Upload, History } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { toast } from 'sonner'
+import { BackupList } from '@/components/backup-list'
function parseMarkdownToNote(content: string, filename: string) {
const lines = content.split('\n')
@@ -144,6 +145,21 @@ export default function SettingsPage() {
+
+
+
+
+
+ Backups
+
+
+ Restaura notas desde backups guardados localmente en tu navegador.
+
+
+
+
+
+
)
diff --git a/src/components/backup-list.tsx b/src/components/backup-list.tsx
new file mode 100644
index 0000000..da31d8a
--- /dev/null
+++ b/src/components/backup-list.tsx
@@ -0,0 +1,136 @@
+'use client'
+import { useState, useEffect } from 'react'
+import { getBackups, deleteBackup } from '@/lib/backup-storage'
+import { RecallBackup } from '@/types/backup'
+import { Button } from '@/components/ui/button'
+import { Badge } from '@/components/ui/badge'
+import { toast } from 'sonner'
+import { Trash2, RotateCcw, Calendar, FileText } from 'lucide-react'
+import { BackupRestoreDialog } from './backup-restore-dialog'
+
+export function BackupList() {
+ const [backups, setBackups] = useState([])
+ const [loading, setLoading] = useState(true)
+ const [deletingId, setDeletingId] = useState(null)
+
+ useEffect(() => {
+ loadBackups()
+ }, [])
+
+ async function loadBackups() {
+ try {
+ const data = await getBackups()
+ setBackups(data)
+ } catch {
+ toast.error('Error al cargar los backups')
+ } finally {
+ setLoading(false)
+ }
+ }
+
+ async function handleDelete(id: string) {
+ setDeletingId(id)
+ try {
+ await deleteBackup(id)
+ setBackups((prev) => prev.filter((b) => b.id !== id))
+ toast.success('Backup eliminado')
+ } catch {
+ toast.error('Error al eliminar el backup')
+ } finally {
+ setDeletingId(null)
+ }
+ }
+
+ function formatDate(dateStr: string) {
+ return new Date(dateStr).toLocaleString('es-ES', {
+ dateStyle: 'medium',
+ timeStyle: 'short',
+ })
+ }
+
+ function getSourceBadgeVariant(source: RecallBackup['source']) {
+ switch (source) {
+ case 'automatic':
+ return 'secondary'
+ case 'manual':
+ return 'default'
+ case 'pre-destructive':
+ return 'destructive'
+ default:
+ return 'secondary'
+ }
+ }
+
+ function getSourceLabel(source: RecallBackup['source']) {
+ switch (source) {
+ case 'automatic':
+ return 'Automático'
+ case 'manual':
+ return 'Manual'
+ case 'pre-destructive':
+ return 'Pre-destrucción'
+ default:
+ return source
+ }
+ }
+
+ if (loading) {
+ return
Cargando backups...
+ }
+
+ if (backups.length === 0) {
+ return (
+
+ No hay backups disponibles. Los backups se crean automáticamente antes de operaciones
+ destructivas.
+