Modelo de datos

Las entidades que las herramientas de WireCat guardan en su almacén local compartido, cómo se conectan y cómo un agente acota el contexto adecuado antes de comparar significados.

Cada herramienta de WireCat — tg, max, memo, zm — guarda lo que lee en un único archivo SQLite local, wirecat.db. Esta página es para desarrolladores y autores de agentes que quieren consultar ese archivo o entender qué puede encontrar un agente en él. Explica primero las entidades, después cómo se conectan, después cómo una búsqueda encuentra contexto y solo al final las columnas por las que vale la pena consultar. Cómo se abre, migra y bloquea el almacén está en el almacén local.

Describe el esquema tal como se leyó el 10 de octubre de 2026, en un commit fijo de cli-messaging, el paquete dueño del archivo. Cada columna con su significado está en la referencia del esquema.

Entidades clave

Cómo se apuntan entre sí las entidades principales

En palabras: una persona tiene identidades; las identidades envían mensajes y correos y participan en reuniones. Una organización agrupa cuentas y proyectos. Cada cuenta trae sus chats, correos, documentos y reuniones; los chats contienen mensajes, y los mensajes se agrupan en conversaciones. Una reunión pertenece a un evento. Un proyecto contiene tareas y decisiones. Una memoria y una etiqueta pueden estar en cualquier entidad, por eso sus líneas punteadas dicen «cualquier entidad»; la línea a la cuenta las representa a todas. Los colores agrupan las tarjetas: personas, chats y correo, la cuenta por la que llegaron, documentos y reuniones, trabajo, y lo que se une a cualquier cosa.

Personas e identidades

Una persona es un ser humano. Una identidad es cómo una fuente conoce a una persona: un usuario de Telegram, un usuario de MAX, una dirección de correo, un participante de Zoom. Una persona tiene muchas identidades; cada identidad pertenece como mucho a una persona, y junto al vínculo se guardan el método y la confianza con que se hizo. Los perfiles anteriores se guardan como revisiones. Un bot es un agente de IA o un script que trabaja en el almacén: puede ser dueño de proyectos, tomar tareas y escribir notas. El bot propio de un mensajero es una identidad, no un bot.

Organizaciones y proyectos

Una organización es una empresa, un equipo, una familia o una comunidad. Un proyecto es un lugar para tareas, con una clave corta (MEET), un tipo (trabajo, cliente, personal, código abierto, otro) y una organización opcional. Las cuentas de trabajo y los proyectos pertenecen a una organización; una familia también es una organización.

Cuentas y chats

Una cuenta es una integración que el dueño conectó: una cuenta de mensajería, un buzón de correo, Zoom, una carpeta de notas. Un chat pertenece a una cuenta. Los chats se anidan: un tema de foro está dentro de su grupo, y el grupo de discusión de un canal está bajo el canal. Un hilo es otra cosa: cuelga de un mensaje raíz dentro de un chat, como los comentarios bajo una publicación de un canal.

Mensajes y conversaciones

Un mensaje pertenece a un chat y lo envía una identidad. Las ediciones conservan el texto anterior, y un mensaje borrado en la fuente conserva su fila sin su texto. Una conversación es un grupo de mensajes de un chat que pertenecen a la misma discusión, reconstruido a partir de respuestas, menciones y del mismo remitente que continúa (cómo se construyen).

Correo

Un correo pertenece a un hilo de correo y a una cuenta. Su remitente y cada destinatario (to, cc, bcc) se resuelven a identidades, así que los correos y los mensajes de la misma persona se encuentran en una sola persona. Las carpetas y etiquetas son buzones; un correo puede estar en varios.

Documentos, notas y memorias

Un documento existe por sí mismo: un archivo en una carpeta de notas, una página, una página de wiki. Una nota es un texto breve que una persona o un bot escribió sobre una cosa: una persona, un chat, una reunión, una tarea; los comentarios de una tarea son notas. Una memoria es lo que concluyó un agente: un resumen, un resumen diario, un hecho, una preferencia. Una memoria puede equivocarse, así que siempre lleva sus pruebas, una confianza y un estado (propuesta, confirmada, obsoleta, sustituida).

Eventos y reuniones

Un evento es el registro del dueño de algo que ocurrió, sin campos de ningún proveedor. Una reunión es una ocurrencia tal como la registró una aplicación de reuniones: sus participantes, transcripciones, chat de la reunión y resúmenes. Una reunión apunta a su evento, así que los registros de la misma llamada desde distintas fuentes se encuentran en un solo evento. Los eventos y las reuniones que se repiten tienen cada uno su serie.

Tareas y decisiones

Una tarea pertenece a un proyecto y se nombra con su clave y su número (MEET-12). Su tipo es error, función, mantenimiento, pregunta, petición, mención o promesa: una pregunta que alguien hizo es una tarea de tipo pregunta, y una promesa que alguien hizo es una tarea de tipo promesa. Personas y bots se asignan con un rol (responsable, revisor, observador), y cada cambio es un evento de la tarea. Una decisión es una elección que vale hasta que otra la sustituye, con sus pruebas vinculadas.

Etiquetas y temas

Una etiqueta es un rótulo libre que cualquiera puede añadir. Un tema es una etiqueta de una lista corta que solo crea el dueño; los agentes pueden proponer uno. Una cosa puede llevar muchas etiquetas y temas, y un tema puede marcarse como el principal. Un nombre es o etiqueta o tema, nunca las dos cosas.

Acciones propuestas y registradas

Una acción propuesta es algo que un agente quiere hacer fuera del almacén — responder, enviar, expulsar, crear una tarea — y que espera a que una persona la apruebe o la rechace. Nada externo ocurre sin esa aprobación. Aparte, cada herramienta que llama un agente queda registrada con su nivel de acceso y su objetivo, sin el texto de sus argumentos.

Cómo se conectan

Cuatro tablas conectan cualquier cosa con cualquier otra, así que ninguna entidad de arriba necesita una columna para cada una de las demás:

  • Los vínculos (links) unen dos cosas con un tipo: una tarea de pregunta con el mensaje que la respondió (answered-by), una decisión o una memoria con su prueba (evidence), una cosa con aquello de lo que se hizo (created-from), una tarea con las personas, mensajes, correos y reuniones a los que se refiere.
  • Las asignaciones de etiquetas (taggings) ponen una etiqueta o un tema en cualquier cosa.
  • Las notas añaden el texto de una persona a cualquier cosa.
  • Los alias (aliases) dan otros nombres a cualquier cosa: un apodo, el nombre de un contacto en un mensajero, el nombre corto de un proyecto. Los leen la búsqueda y la resolución de nombres.

El ámbito (scope) es personal o work. Se fija en cuentas, organizaciones y proyectos, y lo que contienen lo hereda: un chat toma el ámbito de su cuenta salvo que fije el suyo, y una memoria toma el ámbito de sus pruebas. Una pregunta hecha para el trabajo lee solo datos de trabajo, así que nunca trae un chat privado.

Cómo la búsqueda encuentra contexto

Encontrar contexto para un agente son tres pasos, en este orden.

  1. Acotar con tablas. Persona, proyecto, cuenta, tiempo y ámbito son columnas con índices, así que el primer paso es SQL corriente. El índice de participación es el atajo: una fila por persona y por cada mensaje, correo, reunión, tarea o documento en que participó, con su rol, el momento y el ámbito. «Todo lo que Alice Example hizo en el trabajo este mes» es un solo rango del índice.
  2. Buscar palabras y significado solo entre los candidatos. Cada tipo de texto tiene su propio índice de palabras y de raíces: mensajes, correos, adjuntos, documentos, notas, memorias y reuniones. Después los vectores ordenan por significado, y cada fragmento de texto lleva el ámbito, la cuenta, el proyecto y el momento de su origen, así que el recorrido de vectores filtra antes de comparar. Cómo funcionan las palabras, las raíces y los vectores se explica en cómo funciona la búsqueda.
  3. Ampliar por los vínculos. Desde un resultado, seguir la cadena de respuestas, la conversación a la que pertenece, la raíz del hilo, el hilo de correo o la reunión de la que vino una fila de transcripción, y los vínculos que apuntan a él.
SELECT subject_type, subject_id, role, occurred_at
FROM involvements
WHERE person_id = :person AND scope = 'work' AND occurred_at >= :since
ORDER BY occurred_at DESC
LIMIT 50

Los vectores son de los textos largos: conversaciones, documentos, correos, el texto de los adjuntos, notas, memorias, transcripciones y resúmenes de reuniones, eventos y tareas. Un mensaje suelto nunca tiene vector propio; se encuentra por palabras, o por significado a través de su conversación. Un texto se corta en fragmentos, y el vector de cada fragmento se guarda una vez por modelo y hash del texto, así que el mismo texto nunca se vectoriza dos veces.

El índice de participación es derivado: se reconstruye a partir de remitentes, destinatarios, participantes, responsables y vínculos confirmados, y no contiene nada que ellos no tengan.

Tablas

Todas las tablas del almacén por área, con el tipo y el significado de cada columna. Los tiempos son milisegundos de época. La referencia del esquema lista además cada restricción e índice.

Convenciones de nombres

  • Las tablas van en plural y en snake_case. La clave primaria es id; una clave foránea es <singular>_id.
  • external_id es el id propio de la fila en la fuente; el id de otra cosa en la fuente es <thing>_external_id.
  • created_at y updated_at dicen cuándo se guardó y cambió la fila en este archivo. Los momentos del mundo conservan sus nombres: sent_at, joined_at, started_at, due_at.
  • deleted_at significa que desapareció en la fuente. La sincronización nunca borra una fila; solo lo hace una orden del dueño.
  • Un puntero a una fila de cualquier tabla es un texto <name>_type, el nombre de la tabla en singular, y un entero <name>_id. Quien hizo algo o es su dueño es una person o un bot.
  • Lo que se busca tiene su propia columna; metadata es JSON para lo que no.
  • Los indicadores no llevan el prefijo is_. Los tiempos son enteros en milisegundos de época.
  • Cada clave foránea y cada par _type/_id tiene un índice.

Fuentes

Cada integración es una cuenta; cada ejecución de sincronización queda registrada.

accounts

Cada integración que conecta el dueño: una cuenta de mensajería, un buzón, Zoom, una carpeta de notas.

ColumnaTipoSignificado
idinteger, PKClave primaria.
providertext, not nullA qué mensajería pertenece la cuenta, como nombre en minúsculas, p. ej. telegram o max; abierto, para que los adaptadores nuevos no requieran cambios.
external_idtext, not nullel id propio que le da la fuente
nametextEl nombre visible de la cuenta tal como lo informa la mensajería; NULL si no se conoce.
created_atinteger, not nullcuándo se guardó esta fila aquí
settingstextJSON: ajustes de cada integración, p. ej. la ruta y el formato de una carpeta
statustextactive, paused, failed
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez
scopetext, not nullpersonal o work; lo que una consulta de contexto puede leer para un fin dado, para que una pregunta de trabajo nunca traiga chats privados
organization_idinteger → organizations.idla organización a la que pertenece una cuenta de trabajo

sync_cursors

Por cuenta, lo que una sincronización recuerda entre ejecuciones: un marcador de cambios, cuándo una lista estuvo completa por última vez.

ColumnaTipoSignificado
account_idinteger, not null → accounts.idla cuenta de integración por la que llegó
keytext, not nullNombre de lo que una sincronización recuerda para esta cuenta, p. ej. chat_list_complete, history_start:&lt;chatId>, fetched:&lt;chatId>, o un marcador de cambios del proveedor.
valuetext, not nullEl valor recordado como texto (un marcador de cambios, un id de mensaje, una lista JSON); quien llama codifica los números por su cuenta.
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez
created_atinteger, not nullcuándo se guardó esta fila aquí

sync_ranges

Los tramos del historial de cada chat que se tienen completos, para que una descarga sepa qué falta.

ColumnaTipoSignificado
chat_idinteger, not null → chats.idel chat al que pertenece
from_keyinteger, not nullClave de orden más baja del proveedor (el id de mensaje de Telegram) de un tramo del chat que se tiene completo; los mensajes que faltan dentro de él se borraron.
to_keyinteger, not nullClave de orden más alta del proveedor de ese tramo completo; los mensajes fuera de todo tramo simplemente nunca se descargaron.
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

fetch_leases

Quién descarga ahora un tramo de un chat, para que dos procesos no descarguen las mismas páginas.

ColumnaTipoSignificado
chat_idinteger, not null → chats.idel chat al que pertenece
anchortext, not nullQué tramo o trabajo del chat se está descargando, como una etiqueta, p. ej. gaps, para que dos procesos nunca descarguen las mismas páginas.
holdertext, not nullId aleatorio (un UUID) del proceso que tiene la reserva ahora.
expires_atinteger, not nullCuándo vence la reserva (milisegundos de época); después, otro titular puede tomar el tramo.

bot_updates

Cada actualización que una cuenta de bot recibió por la Bot API, guardada tal como llegó, para poder inspeccionarla y reproducirla.

ColumnaTipoSignificado
idinteger, PKClave primaria.
account_idinteger, not null → accounts.idla cuenta del bot
external_idtext, not nullel id de la actualización
kindtext, not nullmensaje, callback, cambio de miembro, …
payloadtext, not nullJSON, exactamente como se recibió
received_atinteger, not nullcuándo llegó la actualización
handled_atintegernull hasta que se procesa
errortextpor qué falló el procesamiento
replayed_atintegercuándo se reprodujo por última vez
created_atinteger, not nullcuándo se guardó esta fila aquí

syncs

Una ejecución de la sincronización de una integración: qué hizo y cómo terminó.

ColumnaTipoSignificado
idinteger, PKClave primaria.
account_idinteger, not null → accounts.idla cuenta de integración por la que llegó
kindtext, not nullfull, incremental, import
started_atinteger, not nullcuándo empezó la ejecución
finished_atintegercuándo terminó; null mientras se ejecuta
statustext, not nullrunning, succeeded, failed
countstextJSON: creados, actualizados, borrados, omitidos
errortextqué detuvo una ejecución fallida, según lo informó el importador
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

Personas, organizaciones y bots

Humanos, las identidades que tienen en cada fuente, las organizaciones a las que pertenecen y los agentes que trabajan aquí.

persons

Un ser humano. Cada persona tiene identidades en las fuentes; una persona es el dueño del almacén.

ColumnaTipoSignificado
idinteger, PKClave primaria.
nametextNombre visible de la persona (tomado del nombre de su primera identidad); NULL si no se conoce ninguno.
ownerinteger, not null1 para la persona dueña del almacén; un almacén nuevo crea esa fila, así que siempre existe.
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

identities

Cómo conoce una fuente a una persona: un usuario de mensajería, una dirección de correo, un participante de una reunión.

ColumnaTipoSignificado
idinteger, PKClave primaria.
providertext, not nullMensajería donde vive la identidad (telegram, max o cualquier texto, p. ej. email); una identidad por proveedor, no por cuenta.
external_idtext, not nullel id propio que le da la fuente
usernametextEl alias público de la persona en esa mensajería, sin @; NULL si no tiene.
nametextEl nombre visible actual de la persona, según lo informó la mensajería por última vez.
botinteger1 si la mensajería dice que esta identidad es un bot, 0 si dice que no, NULL si no se sabe.
phone_hmactextHash con clave (HMAC) del número de teléfono de la persona, para reconocer a la misma persona en distintas mensajerías; el número en sí nunca llega a un log, un fixture ni un documento. Ninguna herramienta lo rellena todavía.
metadatatextJSON: lo que envía la fuente que no tiene columna propia y no se busca
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez
descriptiontextLo que escribieron sobre sí mismos.

A qué persona pertenece una identidad, cómo se decidió y con qué certeza.

ColumnaTipoSignificado
identity_idinteger, PK → identities.idla identidad que se vincula; un vínculo por identidad
person_idinteger, not null → persons.idla person a la que pertenece
methodtext, not nullCómo se asignó la identidad a su persona: initial al verla por primera vez, o una etiqueta de quien llama, p. ej. manual o same-email.
confidencereal, not nullQué tan seguro es el vínculo, de 0 a 1; 1 para cada vínculo que escribe el almacén.
created_atinteger, not nullcuándo se guardó esta fila aquí
authortext, not nullQuién decidió el vínculo: ingest para el primer vínculo automático; si no, owner o el nombre de un programa.
sourcetextqué integración o importador lo propuso
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

Cada traslado de una identidad de una persona a otra, para poder deshacer un vínculo erróneo.

ColumnaTipoSignificado
idinteger, PKClave primaria.
identity_idinteger, not null → identities.idla identity a la que pertenece
from_person_idinteger → persons.idla person a la que pertenece
to_person_idinteger, not null → persons.idla person a la que pertenece
methodtext, not nullCómo se decidió este traslado de una identidad entre personas (initial, manual, same-email…), guardado para poder deshacer un vínculo erróneo.
created_atinteger, not nullcuándo se guardó esta fila aquí
authortext, not nullQuién hizo este traslado: ingest, owner o el nombre de un programa.

identity_revisions

Cada perfil con que se vio a una persona, una fila cuando difiere del anterior; identities guarda el más reciente.

ColumnaTipoSignificado
idinteger, PKClave primaria.
identity_idinteger, not null → identities.idla identity a la que pertenece
nametextEl nombre visible que tenía la persona en esta instantánea de su perfil (solo se añade una fila cuando el perfil cambia).
usernametextEl alias (sin @) que tenía la persona en esta instantánea.
descriptiontextLa biografía o texto «sobre mí» que la persona escribió, en esta instantánea.
markstextJSON: las marcas de la mensajería — bot, estafa, falso, borrado, tiene foto — donde las dio.
created_atinteger, not nullcuándo se guardó esta fila aquí

account_identities

Qué identidades ve cada cuenta, y cuándo habló por última vez con cada una en privado.

ColumnaTipoSignificado
account_idinteger, not null → accounts.idla cuenta de integración por la que llegó
identity_idinteger, not null → identities.idla identity a la que pertenece
created_atinteger, not nullcuándo se guardó esta fila aquí
last_messaged_atintegerEl mensaje más reciente de su chat privado, según lo calculó refreshRecency por última vez: el orden de los contactos.
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

aliases

Otros nombres para cualquier cosa: el apodo de una persona, el nombre de un contacto en una mensajería, el nombre corto de un proyecto. La búsqueda y la coincidencia de nombres los leen.

ColumnaTipoSignificado
idinteger, PKClave primaria.
aliasable_typetext, not nulllo que nombra el alias: identity, person, organization, chat, project, bot, …
aliasable_idinteger, not nullla fila en la tabla aliasable_type
account_idinteger → accounts.idse rellena cuando el alias vale solo visto desde una cuenta, como el nombre de un contacto en una mensajería; null cuando vale en todas partes
nametext, not nullel alias tal como se escribe: un apodo, un nombre corto, un nombre anterior
name_foldedtext, not nullname normalizado para comparar: en minúsculas, sin acentos
displayinteger, not null1 para el alias que se muestra en lugar del nombre real; como mucho uno por cosa y cuenta
sourcetext, not nulldueño, agente, una importación
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

identities_fts

Índice de texto completo sobre name, username.

organizations

Una empresa, equipo, familia o comunidad con la que trata el dueño. Los proyectos, las cuentas de trabajo y las identidades de las personas pertenecen a una.

ColumnaTipoSignificado
idinteger, PKClave primaria.
kindtext, not nullempresa, equipo, familia, comunidad
nametext, not nullel nombre de la organización
scopetext, not nullpersonal o work; lo que una consulta de contexto puede leer para un fin dado, para que una pregunta de trabajo nunca traiga chats privados
metadatatextJSON: lo que envía la fuente que no tiene columna y no se busca
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez
deleted_atintegerdesaparecido en la fuente; la sincronización nunca borra de verdad

bots

Un agente de IA o un script que trabaja aquí: se registra, es dueño de proyectos y tareas, recibe trabajo y escribe notas. Un bot de una mensajería (un bot de Telegram) es una identidad, no esto.

ColumnaTipoSignificado
idinteger, PKClave primaria.
nametext, not null, uniquealias, p. ej. zm-puller
kindtext, not nullagent, script, integration
descriptiontextpara qué sirve el bot, en una frase, escrita al registrarse
owner_person_idinteger → persons.idquién lo ejecuta
modeltextel modelo sobre el que funciona, si es un agente
token_digesttexthash de su token de acceso, para cuando los bots se autentiquen
last_seen_atintegerla última vez que el bot hizo algo aquí
disabled_atintegerse rellena cuando el dueño apaga el bot; conserva lo que posee
metadatatextJSON: lo que envía la fuente que no tiene columna y no se busca
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

Chats y mensajes

Lo que traen las mensajerías.

chats

Un lugar para hablar en una cuenta: un diálogo, grupo, canal o mensajes guardados. Los chats pueden anidarse.

ColumnaTipoSignificado
idinteger, PKClave primaria.
account_idinteger, not null → accounts.idla cuenta de integración por la que llegó
external_idtext, not nullel id propio que le da la fuente
kindtext, not nullTipo de chat: dialog (privado), group, channel, saved (notas para uno mismo) o unknown.
titletextEl nombre del chat tal como lo muestra la mensajería; NULL si no tiene.
unread_countintegerMensajes no leídos que informó la mensajería; NULL significa que la mensajería no lo dijo, lo que no es cero.
last_message_atintegerHora del mensaje más reciente del chat (milisegundos de época); NULL si nunca tuvo uno.
participants_countintegerNúmero de miembros que informó la mensajería; NULL si no se dio.
metadatatextJSON: lo que envía la fuente que no tiene columna propia y no se busca
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez
usernametextEl alias público del chat (sin @) cuando tiene uno, p. ej. un canal público.
membership_statetextNULL es desconocido. De él no se deduce si se puede buscar: un chat abandonado conserva sus mensajes.
searchableinteger, not null1 si los mensajes del chat aparecen en búsquedas que no lo nombran, 0 si solo los ve una búsqueda que nombra el chat.
message_countinteger, not nullLo mantienen los triggers, para que una consulta pueda elegir cómo llega un filtro al índice.
members_tracked_atintegerCuándo pidió el dueño a serve que descargue su lista de miembros a diario; NULL si no se sigue.
descriptiontextla descripción del chat, tal como la da la mensajería
details_fetched_atintegercuándo se leyeron por última vez el título, el alias y la descripción
created_atinteger, not nullcuándo se guardó esta fila aquí
parent_chat_idinteger → chats.idel chat dentro del que está este: un tema de foro en su grupo, el grupo de discusión de un canal, un canal en un espacio de trabajo
scopetextsustituye el ámbito de la cuenta para este chat; null toma el de la cuenta

chat_members

Quién está en un chat, según lo vio la cuenta por última vez: una lista reemplaza entera la membresía del chat.

ColumnaTipoSignificado
chat_idinteger, not null → chats.idel chat al que pertenece
identity_idinteger, not null → identities.idla identity a la que pertenece
created_atinteger, not nullcuándo se guardó esta fila aquí

member_stays

Una estancia de una persona en un grupo, a partir de listas de miembros leídas enteras o en parte. Una vuelta tras irse es una fila nueva. gone_at solo se rellena con una lista leída entera: una lista cortada no dice nada de quién falta.

ColumnaTipoSignificado
idinteger, PKClave primaria.
chat_idinteger, not null → chats.idel chat al que pertenece
identity_idinteger, not null → identities.idla identity a la que pertenece
first_seen_atinteger, not nullCuándo una lectura de la lista de miembros mostró por primera vez a la persona en el grupo en esta estancia (milisegundos de época).
last_seen_atinteger, not nullCuándo una lectura de la lista de miembros mostró por última vez a la persona en el grupo (milisegundos de época).
joined_atintegerCuándo dice la mensajería que se unió; NULL donde no lo dice.
invited_by_identity_idinteger → identities.idla identity a la que pertenece
roletextEl rol de la persona en el grupo en la última lectura: owner, admin o member; NULL si no se dio.
left_atintegerCuándo una lista completa de miembros dejó de incluir a la persona por primera vez, cerrando esta estancia (milisegundos de época); NULL mientras sigue en ella.
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

member_counts

El tamaño de un grupo una vez al día: el recuento propio de la mensajería y cuántos miembros listó una lectura.

ColumnaTipoSignificado
chat_idinteger, not null → chats.idel chat al que pertenece
datetext, not nullYYYY-MM-DD, UTC; SQLite no tiene tipo fecha
reported_countintegerel recuento que informa la mensajería
listed_countinteger, not nullcuántos miembros devolvió de verdad una lectura
complete_listinteger, not nullsi esa lectura devolvió la lista entera
created_atinteger, not nullcuándo se guardó esta fila aquí

messages

Un mensaje en un chat, con su texto, remitente, respuesta e hilo.

ColumnaTipoSignificado
idinteger, PKClave primaria.
chat_idinteger, not null → chats.idel chat al que pertenece
account_idinteger, not null → accounts.idla cuenta de integración por la que llegó
external_idtext, not nullel id propio que le da la fuente
thread_external_idtextEl id que da la mensajería al tema o hilo del chat al que pertenece el mensaje, donde la mensajería tiene hilos.
sender_identity_idinteger → identities.idla identity a la que pertenece
sender_chat_external_idtextEl id que da la mensajería al chat autor del mensaje (una publicación de canal o un mensaje enviado como el grupo); NULL para una persona.
sender_nametextEl nombre visible del remitente tal como viene en este mensaje.
sent_atinteger, not nullCuándo se envió el mensaje (milisegundos de época).
edited_atintegerCuándo registró la mensajería la última edición (milisegundos de época); NULL para un mensaje nunca cambiado.
deleted_atintegercuándo desapareció en la fuente; la fila se queda, la sincronización nunca borra de verdad
texttext, not nullEl texto del mensaje exactamente como se recibió (cadena vacía si no tiene o se borró).
reply_to_external_idtextEl id que da la mensajería al mensaje al que este responde, aunque no se haya enviado una copia de él.
reply_totextCopia JSON del mensaje respondido tal como la envió la mensajería (id, remitente, hora, texto, adjuntos); NULL si no se envió.
forwardtextCopia JSON del mensaje original que este reenvía (misma forma que reply_to); NULL si no es un reenvío.
outgoinginteger1 si lo envió esta cuenta, 0 si lo envió otra persona, NULL si no se conoce la identidad propia de la cuenta.
reactionstextJSON de las reacciones: recuentos por reacción, la reacción propia de esta cuenta y el total; NULL si nunca se pidieron.
metadatatextJSON: lo que envía la fuente que no tiene columna propia y no se busca
created_atinteger, not nullcuándo se guardó esta fila aquí
sourcetext, not nullCómo llegó el mensaje al almacén, p. ej. history, send, backfill, update, context; solo para diagnóstico.
normalized_texttextel texto normalizado para buscar: en minúsculas, sin acentos; lo rellena el indexador
normalizer_versionintegerVersión de las reglas de normalización de texto que produjeron el texto de búsqueda del mensaje (ahora 1); NULL hasta que se normaliza.
mentionstextJSON: las personas que el texto menciona por id, donde la mensajería lo indica; los @handle se leen del texto.
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez
thread_root_idinteger → messages.idel mensaje del que cuelga un hilo: un hilo de Slack, los comentarios bajo una publicación de canal, las respuestas en un tema; null fuera de un hilo

message_revisions

Textos anteriores de un mensaje, una fila por edición.

ColumnaTipoSignificado
idinteger, PKClave primaria.
message_idinteger, not null → messages.idel message al que pertenece
texttext, not nullEl texto del mensaje antes de que una edición lo reemplazara.
edited_atintegerLa hora de edición (milisegundos de época) que tenía el mensaje mientras tuvo este texto anterior; NULL si no se había editado antes.
created_atinteger, not nullcuándo se guardó esta fila aquí

Cada candidato a «el mensaje anterior al que este responde», y de dónde salió.

ColumnaTipoSignificado
idinteger, PKClave primaria.
chat_idinteger, not null → chats.idEl chat del mensaje, guardado aquí para que una reconstrucción encuentre y descarte una construcción antigua sin leer messages.
message_idinteger, not null → messages.idel message al que pertenece
parent_idinteger → messages.idNULL: la fuente dice que este mensaje empieza una conversación.
sourcetext, not nullQuién propuso este padre para el mensaje: provider (la respuesta propia de la mensajería), rule o agent.
kindtext, not nullPor qué el mensaje se vincula a su padre: reply, mention, same_sender (reglas/proveedor) o answer (elección de un agente).
confidencereal, not nullQué tan segura está la fuente de que este es el padre correcto, de 0 a 1.
methodtext, not nullEl nombre de la regla, o el modelo del agente.
versiontextPara vínculos de proveedor y de regla, la versión de las reglas de vinculación que lo escribió (como texto); para vínculos de agente, la versión de la skill del agente, si se dio.
batchtextQué lote de agente lo escribió.
buildintegerLa reconstrucción que escribió un vínculo de proveedor o de regla; NULL para el de un agente, que sobrevive a las reconstrucciones.
created_atinteger, not nullcuándo se guardó esta fila aquí
stale_atintegerUn extremo del vínculo cambió después de escribirse; nunca se elige hasta que se vuelva a pedir.
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

message_counter_observations

El valor más reciente del contador de vistas, reacciones o comentarios de un mensaje.

ColumnaTipoSignificado
message_idinteger, not null → messages.idel message al que pertenece
countertext, not nullQué contador se observó: views, reactions o comments.
valuereal, not nullEl valor del contador en la observación (un número no negativo).
created_atinteger, not nullcuándo se guardó esta fila aquí
sourcetext, not nullCómo se observó: remote_fetch (lo pidió el almacén) o remote_update (la mensajería envió un cambio).

message_transcripts

Lo que dijo un mensaje de voz, con clave por chat e id de mensaje en lugar de una fila de mensaje: un mensaje puede escucharse antes de que el almacén lo tenga. Derivado: puede volver a escucharse.

ColumnaTipoSignificado
idinteger, PKClave primaria.
message_idinteger → messages.idse rellena cuando el mensaje se guarda
chat_idinteger, not null → chats.idel chat al que pertenece
message_external_idtext, not nullEl id que da la mensajería al mensaje de voz transcrito; con esta clave porque un mensaje puede escucharse antes de guardarse.
texttext, not nullLo que dijo el mensaje de voz, transcrito; nunca vacío.
sourcetext, not nullEl modelo o la mensajería que lo escuchó.
heard_atinteger, not nullCuándo se hizo la transcripción (milisegundos de época).
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

chats_fts

Índice de texto completo sobre title.

messages_fts

Índice de texto completo sobre text.

message_words

Índice de texto completo sobre normalized_text, scope.

message_stems

Índice de texto completo sobre stems, scope.

message_stems_pending

Mensajes cuyas raíces están desactualizadas. Los triggers la llenan, porque SQL no puede extraer raíces; JS la vacía.

ColumnaTipoSignificado
idinteger, PKClave primaria.

member_observations

Una lectura de la lista de miembros de un chat: cuándo, si fue la lista entera, y cuántos informó y devolvió. La retención lee de aquí la presencia en un punto de control.

ColumnaTipoSignificado
idinteger, PKClave primaria.
chat_idinteger, not null → chats.idel chat al que pertenece
observed_atinteger, not nullcuándo se leyó la lista de miembros
started_atintegercuándo empezó la lectura, para una lista leída por páginas
completeinteger, not null1 cuando la lectura devolvió la lista entera, así que un miembro que falta en ella se ha ido
reported_countintegerel recuento que informa la mensajería
listed_countinteger, not nullcuántos miembros devolvió esta lectura
sourcetext, not nullqué la leyó: una sincronización, un comando, una importación
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

member_observation_members

A quién vio una lectura de la lista de miembros.

ColumnaTipoSignificado
member_observation_idinteger, not null → member_observations.idla member_observation a la que pertenece
identity_idinteger, not null → identities.idla identity a la que pertenece
member_stay_idinteger, not null → member_stays.idla estancia en la que estaba el miembro cuando se le vio

Correo

El correo tiene tablas propias: hilos, asuntos, destinatarios, buzones.

email_threads

Una conversación por correo.

ColumnaTipoSignificado
idinteger, PKClave primaria.
account_idinteger, not null → accounts.idla cuenta de integración por la que llegó
external_idtext, not nullid de hilo de Gmail, o derivado de References
subjecttextel asunto del primer correo del hilo, sin Re: ni Fwd:
last_email_atintegercuándo se envió el correo más reciente del hilo
emails_countinteger, not nullcuántos correos del hilo están guardados
metadatatextJSON: lo que envía la fuente que no tiene columna y no se busca
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez
deleted_atintegerdesaparecido en la fuente; la sincronización nunca borra de verdad

emails

Un correo.

ColumnaTipoSignificado
idinteger, PKClave primaria.
account_idinteger, not null → accounts.idla cuenta de integración por la que llegó
email_thread_idinteger, not null → email_threads.idel email_thread al que pertenece
external_idtext, not nullla cabecera Message-ID
subjecttextla cabecera Subject, decodificada
from_identity_idinteger → identities.idla identity a la que pertenece
from_addresstextla dirección del remitente, en minúsculas
from_nametextel nombre visible del remitente, tal como está en From
sent_atintegerla cabecera Date
received_atintegercuándo lo recibió el buzón del dueño
in_reply_totextel Message-ID al que responde este correo
referencestextJSON: la cabecera References
body_texttextel cuerpo en texto plano; derivado del HTML cuando el correo no tiene parte de texto
body_htmltextel cuerpo HTML, tal como se recibió
snippettextlas primeras palabras del cuerpo, para listados
outgoinginteger1 cuando lo envió el dueño
readinteger1 cuando está marcado como leído en el buzón
flaggedinteger1 cuando está marcado o destacado
draftinteger1 para un borrador aún no enviado
sizeintegerel tamaño del correo en bruto, en bytes
headerstextJSON: todas las cabeceras, tal como se recibieron
metadatatextJSON: lo que envía la fuente que no tiene columna y no se busca
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez
deleted_atintegerdesaparecido en la fuente; la sincronización nunca borra de verdad

email_recipients

Una dirección de un correo.

ColumnaTipoSignificado
idinteger, PKClave primaria.
email_idinteger, not null → emails.idel email al que pertenece
identity_idinteger → identities.idla identity a la que pertenece
addresstext, not nullla dirección, en minúsculas
nametextel nombre visible escrito junto a ella
roletext, not nullto, cc, bcc, reply_to
positioninteger, not nullorden dentro de su padre, desde 0
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

mailboxes

Una carpeta IMAP o una etiqueta de Gmail. Las etiquetas propias del dueño son asignaciones de etiqueta.

ColumnaTipoSignificado
idinteger, PKClave primaria.
account_idinteger, not null → accounts.idla cuenta de integración por la que llegó
external_idtext, not nullel id propio que le da la fuente
nametext, not nullel nombre de la carpeta o etiqueta tal como lo muestra el proveedor
kindtextinbox, sent, archive, label, folder
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

email_mailboxes

En qué buzones está un correo; Gmail pone un correo en varios.

ColumnaTipoSignificado
email_idinteger, not null → emails.idel email al que pertenece
mailbox_idinteger, not null → mailboxes.idel mailboxe al que pertenece
created_atinteger, not nullcuándo se guardó esta fila aquí

email_words

Índice de texto completo sobre normalized_text, scope.

email_stems

Índice de texto completo sobre stems, scope.

email_index_pending

Filas de correos que esperan ser indexadas: los triggers las encolan, JS normaliza, extrae las raíces y escribe el índice.

ColumnaTipoSignificado
idinteger, not nullLa fila que espera ser indexada.
indexable_typetext, not nulla qué tabla pertenece la fila en espera

Adjuntos

Archivos de un mensaje, un correo o una reunión, con su texto extraído.

attachments

Un archivo de un mensaje, un correo o una reunión, con su texto extraído.

ColumnaTipoSignificado
idinteger, PKClave primaria.
attachable_typetext, not nullmessage, email o meeting
attachable_idinteger, not nullla fila en la tabla attachable_type
positioninteger, not nullorden dentro de su padre, desde 0
kindtext, not nullTipo del adjunto en minúsculas, p. ej. photo, video, file, voice, sticker, share.
mimetextEl tipo MIME del archivo, donde la mensajería lo da.
nametextEl nombre del archivo, donde la mensajería lo da.
titletextTítulo de una página web compartida (para adjuntos share).
urltextUn enlace que abre los bytes o la página compartida, cuando la mensajería lo entrega.
sizeintegerTamaño del archivo en bytes, donde la mensajería lo da.
widthintegerAncho en píxeles para imágenes y video.
heightintegerAlto en píxeles para imágenes y video.
durationrealDuración en segundos para audio y video.
provider_reftextJSON opaco que el adaptador de la mensajería necesita para descargar los bytes después; no significa nada fuera de ese adaptador.
local_pathtextDónde guardó messages download el archivo en este equipo; NULL si nunca se descargó.
texttextel texto extraído del archivo
normalized_texttextel texto normalizado para buscar: en minúsculas, sin acentos; lo rellena el indexador
extractiontextcómo se obtuvo el texto: text, ocr, agent, failed
extractortextQué produjo el texto del adjunto: plain, docx:[email protected], pdf:[email protected], un motor de OCR o la etiqueta propia de un agente.
extraction_errortextCódigo corto de por qué no salió texto (p. ej. no_text), nunca una línea del archivo; NULL si tuvo éxito.
content_sha256textSHA-256 en hexadecimal de los bytes del archivo que se leyeron, para no volver a leer un archivo sin cambios.
extracted_atintegerCuándo se escribió el texto del adjunto (o su error) (milisegundos de época).
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

attachment_words

Índice de texto completo sobre normalized_text.

Documentos, notas y memorias

Los documentos son archivos y páginas independientes; las notas son lo que una persona escribió sobre algo; las memorias son lo que concluyó un agente.

documents

Un archivo o página independiente: un archivo en una carpeta de notas (md, pdf, docx, xlsx…), una página de Notion, un archivo de Drive, una página wiki de memo.

ColumnaTipoSignificado
idinteger, PKClave primaria.
account_idinteger, not null → accounts.idla carpeta, Notion, Drive
external_idtext, not nullruta en la carpeta, id de página, id de archivo
kindtext, not nullfile, page, wiki
titletextdel front matter, el primer encabezado o el nombre del archivo, en ese orden
locationtextdónde vive en su fuente: la ruta de la carpeta, la carpeta de Drive, la página padre de Notion
file_nametextcon su extensión; null para una página que no es un archivo
extensiontexten minúsculas, sin el punto: md, pdf, docx
urltextdónde lo abre la fuente
storagetextlocal, drive, notion, web: dónde están los bytes
local_pathtextuna copia en este equipo, cuando se guarda una; para una carpeta local, el propio archivo
mimetextel tipo de medio, p. ej. application/pdf
sizeintegerel tamaño del archivo, en bytes
content_hashtexthash de los bytes del archivo; un archivo sin cambios no se vuelve a leer
front_mattertextJSON, tal como está escrito en el archivo
bodytextMarkdown tal cual; texto extraído para PDF y Office; OCR para escaneos
normalized_texttextel texto normalizado para buscar: en minúsculas, sin acentos; lo rellena el indexador
extractiontextnone, text, ocr, agent, failed
extraction_errortextpor qué no se pudo extraer el texto
languagetextidioma detectado del cuerpo, como código ISO 639-1
revisioninteger, not nullcontador de ediciones, sube con cada cambio; una edición nombra la revisión que leyó, para que dos escritores no se sobrescriban
export_pathtextdónde lo exportó memo, para páginas wiki
external_created_atintegercuándo dice la fuente que se creó
external_updated_atintegercuándo dice la fuente que cambió por última vez
metadatatextJSON: lo que envía la fuente que no tiene columna y no se busca
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez
deleted_atintegerdesaparecido en la fuente; la sincronización nunca borra de verdad

document_revisions

Cuerpos anteriores de un documento.

ColumnaTipoSignificado
idinteger, PKClave primaria.
document_idinteger, not null → documents.idel document al que pertenece
bodytext, not nullel cuerpo tal como era antes de esa revisión
revisioninteger, not nullcontador de ediciones, sube con cada cambio; una edición nombra la revisión que leyó, para que dos escritores no se sobrescriban
created_atinteger, not nullcuándo se guardó esta fila aquí

document_words

Índice de texto completo sobre normalized_text, scope.

document_stems

Índice de texto completo sobre stems, scope.

document_index_pending

Filas de documentos que esperan ser indexadas: los triggers las encolan, JS normaliza, extrae las raíces y escribe el índice.

ColumnaTipoSignificado
idinteger, not nullLa fila que espera ser indexada.
indexable_typetext, not nulla qué tabla pertenece la fila en espera

notes

Texto corto sobre algo: una persona, un chat, un evento, un documento, una tarea. Los comentarios en una tarea también son notas.

ColumnaTipoSignificado
idinteger, PKClave primaria.
notable_typetext, not nullde qué trata la nota: person, chat, event, document, task, …; una nota sobre nada en concreto trata de la persona del dueño
notable_idinteger, not nullla fila en la tabla notable_type
titletextencabezado opcional
bodytext, not nullla nota, en Markdown
author_typetextperson o bot
author_idintegerla fila en la tabla author_type
revisioninteger, not nullcontador de ediciones, sube con cada cambio; una edición nombra la revisión que leyó, para que dos escritores no se sobrescriban
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez
deleted_atintegerdesaparecido en la fuente; la sincronización nunca borra de verdad

note_revisions

Cuerpos anteriores de una nota.

ColumnaTipoSignificado
idinteger, PKClave primaria.
note_idinteger, not null → notes.idla note a la que pertenece
bodytext, not nullel cuerpo tal como era antes de esa revisión
revisioninteger, not nullcontador de ediciones, sube con cada cambio; una edición nombra la revisión que leyó, para que dos escritores no se sobrescriban
created_atinteger, not nullcuándo se guardó esta fila aquí

note_words

Índice de texto completo sobre normalized_text, scope.

note_stems

Índice de texto completo sobre stems, scope.

note_index_pending

Filas de notas que esperan ser indexadas: los triggers las encolan, JS normaliza, extrae las raíces y escribe el índice.

ColumnaTipoSignificado
idinteger, not nullLa fila que espera ser indexada.
indexable_typetext, not nulla qué tabla pertenece la fila en espera

memories

Lo que concluyó un agente: un resumen, un resumen diario, un hecho, una preferencia. Derivada y falible, por eso lleva su evidencia (links de tipo evidence), su confianza y su estado; las notas son lo que escribió una persona.

ColumnaTipoSignificado
idinteger, PKClave primaria.
kindtext, not nullsummary, digest, fact, preference
bodytext, not nullel texto de la memoria
subject_typetextde qué trata: person, chat, meeting, project, …; null para un hecho general
subject_idintegerla fila en la tabla subject_type
author_typetext, not nullperson o bot
author_idinteger, not nullla fila en la tabla author_type
modeltextel modelo que la escribió
confidencereal0–1, según lo valoró el autor
statustext, not nullproposed, confirmed, stale, superseded
last_verified_atintegercuándo se comprobó su evidencia por última vez
supersedes_idinteger → memories.idla memoria que esta reemplaza
scopetext, not nullpersonal o de trabajo, según su evidencia
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

memory_words

Índice de texto completo sobre normalized_text, scope.

memory_stems

Índice de texto completo sobre stems, scope.

memory_index_pending

Filas de memorias que esperan ser indexadas: los triggers las encolan, JS normaliza, extrae las raíces y escribe el índice.

ColumnaTipoSignificado
idinteger, not nullLa fila que espera ser indexada.
indexable_typetext, not nulla qué tabla pertenece la fila en espera

Eventos y reuniones

Los eventos del dueño, y el registro que cada app de reuniones tiene de ellos.

event_series

Un evento que se repite, por encima de la recurrencia de cualquier proveedor.

ColumnaTipoSignificado
idinteger, PKClave primaria.
titletextcómo se llama el evento que se repite, p. ej. la sincronización semanal
recurrencetextRRULE cuando se conoce
origintext, not nullauto o dueño
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

events

El registro propio del dueño de algo que ocurrió, igual que una persona es el registro del dueño de alguien. No tiene campos de proveedor: las fuentes apuntan a él.

ColumnaTipoSignificado
idinteger, PKClave primaria.
event_series_idinteger → event_series.idla event_sery a la que pertenece
titletextel título del dueño; se rellena con la primera reunión o entrada de calendario vinculada
descriptiontextde qué trata el evento
locationtextdónde ocurre: una dirección, una sala o en línea
starts_atintegercuándo empieza
ends_atintegercuándo termina
timezonetextzona IANA en la que se celebra el evento, p. ej. Europe/Madrid
origintext, not nullauto o dueño
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez
deleted_atintegerdesaparecido en la fuente; la sincronización nunca borra de verdad

meeting_series

Una reunión recurrente o programada de un proveedor.

ColumnaTipoSignificado
idinteger, PKClave primaria.
account_idinteger, not null → accounts.idla cuenta de integración por la que llegó
external_idtext, not nullid de reunión de Zoom
event_series_idinteger → event_series.idla event_sery a la que pertenece
titletextel tema de la reunión en el proveedor
descriptiontextel orden del día, tal como lo guarda el proveedor
kindtextinstant, scheduled, recurring
recurrencetextJSON, la regla del proveedor
host_identity_idinteger → identities.idla identity a la que pertenece
join_urltextel enlace para unirse; también lo que después se compara con una entrada de calendario
metadatatextJSON: lo que envía la fuente que no tiene columna y no se busca
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez
deleted_atintegerdesaparecido en la fuente; la sincronización nunca borra de verdad

meetings

Una ocurrencia: pasó una vez, en un momento.

ColumnaTipoSignificado
idinteger, PKClave primaria.
account_idinteger, not null → accounts.idla cuenta de integración por la que llegó
meeting_series_idinteger → meeting_series.idla meeting_sery a la que pertenece
event_idinteger → events.idlo rellena la vinculación de eventos
external_idtext, not nullUUID de ocurrencia de Zoom
titletextel tema de esta ocurrencia
descriptiontextorden del día; también lo que lleva una entrada de calendario
locationtextuna sala física, cuando el proveedor la indica
join_urltextel enlace para unirse a esta ocurrencia
started_atintegercuándo empezó la ocurrencia
ended_atintegercuándo terminó
duration_msintegercuánto duró, en milisegundos
timezonetextzona IANA que da el proveedor para la reunión
host_identity_idinteger → identities.idla identity a la que pertenece
participants_countintegercuántos participaron, según informa el proveedor
metadatatextJSON: lo que envía la fuente que no tiene columna y no se busca
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez
deleted_atintegerdesaparecido en la fuente; la sincronización nunca borra de verdad

meeting_participants

Una persona en una reunión, tal como esa reunión la vio; el nombre y el correo se quedan con esta reunión.

ColumnaTipoSignificado
idinteger, PKClave primaria.
meeting_idinteger, not null → meetings.idla meeting a la que pertenece
identity_idinteger, not null → identities.idcon clave por el id de usuario del proveedor; si no, el correo; si no, name@meeting
display_nametextel nombre mostrado en esta reunión; un cambio de nombre posterior no lo cambia
emailtextla dirección que da el proveedor, cuando la da
roletexthost, co-host, attendee, panelist, guest
joined_atintegerprimera entrada
left_atintegerúltima salida
duration_msintegertiempo en la reunión, sumado sobre todas las entradas
sessionstextJSON: cada entrada y salida
external_idtextel id propio que le da la fuente
metadatatextJSON: lo que envía la fuente que no tiene columna y no se busca
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

meeting_transcripts

Una transcripción de una reunión: la de Zoom, la de un bot o una versión corregida, que sustituye a la anterior.

ColumnaTipoSignificado
idinteger, PKClave primaria.
meeting_idinteger, not null → meetings.idla meeting a la que pertenece
sourcetext, not nullapi, file, fireflies
formattextvtt
languagetextel idioma de la transcripción, como código ISO 639-1
content_hashtextel mismo archivo importado dos veces se omite
external_created_atintegercuándo dice la fuente que se creó
superseded_atintegerse rellena cuando una transcripción más nueva de la misma reunión reemplaza a esta; esta se conserva
metadatatextJSON: lo que envía la fuente que no tiene columna y no se busca
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez
deleted_atintegerdesaparecido en la fuente; la sincronización nunca borra de verdad

meeting_transcript_rows

Una fila de una transcripción (un cue de WebVTT): quién habló, cuándo y qué dijo.

ColumnaTipoSignificado
idinteger, PKClave primaria.
meeting_transcript_idinteger, not null → meeting_transcripts.idla meeting_transcript a la que pertenece
positioninteger, not nullorden dentro de su padre, desde 0
start_msinteger, not nullcuándo empieza la fila, en milisegundos desde el inicio de la grabación
end_msinteger, not nullcuándo termina
speaker_participant_idinteger → meeting_participants.idel participante cuyo nombre da el cue, buscado dentro de la reunión; null cuando no coincide un único participante
speaker_nametexttal como está escrito en el cue
texttext, not nulllo que se dijo, sin el prefijo del hablante
normalized_texttextel texto normalizado para buscar: en minúsculas, sin acentos; lo rellena el indexador
metadatatextJSON: lo que envía la fuente que no tiene columna y no se busca
created_atinteger, not nullcuándo se guardó esta fila aquí

meeting_chat_messages

El chat dentro de la reunión.

ColumnaTipoSignificado
idinteger, PKClave primaria.
meeting_idinteger, not null → meetings.idla meeting a la que pertenece
external_idtextel id propio que le da la fuente
sent_atinteger, not nullcuándo se envió
sender_participant_idinteger → meeting_participants.idel meeting_participant al que pertenece
sender_nametextel nombre del remitente tal como lo muestra el chat
recipienttexttodos, o un nombre para un mensaje privado
texttext, not nullel mensaje
normalized_texttextel texto normalizado para buscar: en minúsculas, sin acentos; lo rellena el indexador
metadatatextJSON: lo que envía la fuente que no tiene columna y no se busca
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

meeting_summaries

Un resumen de una reunión, de la IA del proveedor, un bot, el dueño o un LLM ejecutado aquí.

ColumnaTipoSignificado
idinteger, PKClave primaria.
meeting_idinteger, not null → meetings.idla meeting a la que pertenece
sourcetext, not nullzoom-ai, fireflies, owner, llm
titletextel título propio del resumen
overviewtextel párrafo corto del resumen
sectionstextJSON: [{label, text}]
next_stepstextJSON: [text]
contenttextel texto completo del proveedor
doc_urltextun enlace al resumen en el proveedor, cuando lo tiene
external_created_atintegercuándo dice la fuente que se creó
external_updated_atintegercuándo dice la fuente que cambió por última vez
metadatatextJSON: lo que envía la fuente que no tiene columna y no se busca
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

meeting_words

Índice de texto completo sobre normalized_text, scope.

meeting_stems

Índice de texto completo sobre stems, scope.

meeting_index_pending

Filas de transcripciones, chat de reuniones y resúmenes que esperan ser indexadas: los triggers las encolan, JS normaliza, extrae las raíces y escribe el índice.

ColumnaTipoSignificado
idinteger, not nullLa fila que espera ser indexada.
indexable_typetext, not nulla qué tabla pertenece la fila en espera

Tareas

Un sistema de tareas y tickets para personas y agentes: proyectos con claves, tareas con tipo y prioridad, asignados que son personas o bots, y las decisiones tomadas por el camino. Una promesa es una tarea de tipo promise; una pregunta es una tarea de tipo question cuya respuesta está vinculada.

reminders

Cuándo recordarle a alguien una tarea, y si el recordatorio se entregó.

ColumnaTipoSignificado
idinteger, PKClave primaria.
task_idinteger, not null → tasks.idla task a la que pertenece
account_idinteger, not null → accounts.idla cuenta de integración por la que llegó
due_atinteger, not nullCuándo debe saltar el recordatorio (milisegundos de época).
timezonetext, not nullZona horaria IANA en la que se programó el recordatorio, p. ej. Europe/Madrid.
statetext, not nullEstado de entrega: pending, leased (reservado por un entregador), delivered o cancelled.
revisioninteger, not nullcontador de ediciones, sube con cada cambio; una edición nombra la revisión que leyó, para que dos escritores no se sobrescriban
lease_untilintegerHasta cuándo tiene el recordatorio el entregador actual (milisegundos de época); después, otro puede reservarlo. NULL salvo si está reservado.
receipttextId que se da al entregador al reservar, y que debe devolver para confirmar la entrega; NULL si no está reservado.
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

projects

Un lugar para tareas, con la clave corta con la que empiezan sus ids (MEET-12).

ColumnaTipoSignificado
idinteger, PKClave primaria.
keytext, not null, uniqueen mayúsculas, p. ej. MEET
nametext, not nullel nombre del proyecto
descriptiontextpara qué sirve el proyecto
typetext, not nullwork, client, personal, oss, other; las etiquetas agrupan proyectos más allá de eso
organization_idinteger → organizations.idla organization a la que pertenece
account_idinteger → accounts.idla cuenta para la que un proyecto bandeja de entrada reúne tareas; null para un proyecto propio del dueño
scopetext, not nullpersonal o work; lo que una consulta de contexto puede leer para un fin dado, para que una pregunta de trabajo nunca traiga chats privados
owner_typetextperson o bot
owner_idintegerla fila en la tabla owner_type
tasks_countinteger, not nullel último número asignado; la siguiente tarea toma +1 en la misma transacción
statustextactive, archived
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez
deleted_atintegerdesaparecido en la fuente; la sincronización nunca borra de verdad

tasks

Una tarea o ticket, para personas y agentes por igual. Todo lo que le concierne — personas, mensajes, correos, documentos, reuniones — es una fila de links; sus etiquetas son asignaciones de etiqueta; sus comentarios son notas.

ColumnaTipoSignificado
idinteger, PKClave primaria.
project_idinteger, not null → projects.idel project al que pertenece
numberinteger, not nullpor proyecto
keytext, not null, unique&lt;project key>-&lt;number>, el id que usan personas y agentes
titletext, not nulluna línea que dice qué hay que hacer
descriptiontextel detalle, en Markdown
typetext, not nullbug, feature, chore, question, request, mention, promise: las cuatro últimas son las que el paquete de tareas encuentra en los mensajes
statustext, not nullopen, in_progress, blocked, done, dismissed
priorityinteger0 urgente … 4 baja
parent_idinteger → tasks.idel padre de una subtarea
due_atintegercuándo debe estar hecha
started_atintegercuándo la empezó alguien (estado in_progress)
closed_atintegercuándo pasó a done o dismissed
closed_by_typetextperson o bot
closed_by_idintegerla fila en la tabla closed_by_type
close_reasontextpor qué se cerró, en pocas palabras, p. ej. no-reply-needed
author_typetext, not nullperson o bot
author_idinteger, not nullla fila en la tabla author_type
sourcetext, not nulldueño, agente, regla o una importación
package_idtext, uniqueel id propio del paquete de tareas para la tarea; null para una tarea creada aquí
source_locatortextde dónde salió la tarea: un localizador de mensaje, nunca su texto
source_kindtextel tipo de cosa que nombra source_locator
source_grouptextel grupo en el que la archiva el paquete de tareas
resolutiontextcómo terminó, en palabras; la respuesta de una pregunta. De dónde vino la respuesta es una fila de links de tipo answered-by
verdicttextuseful o not_useful, según juzgó el dueño una tarea que planteó un agente; null hasta que se juzga
metadatatextJSON: lo que envía la fuente que no tiene columna y no se busca
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez
deleted_atintegerdesaparecido en la fuente; la sincronización nunca borra de verdad

task_assignments

Quién trabaja en una tarea: una persona o un bot, en un rol.

ColumnaTipoSignificado
idinteger, PKClave primaria.
task_idinteger, not null → tasks.idla task a la que pertenece
assignee_typetext, not nullperson o bot
assignee_idinteger, not nullla fila en la tabla assignee_type
roletext, not nullassignee, reviewer, watcher
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

task_events

El historial de una tarea: creada, cambio de estado, asignada, fecha límite movida.

ColumnaTipoSignificado
idinteger, PKClave primaria.
task_idinteger, not null → tasks.idla task a la que pertenece
actor_typetextperson o bot
actor_idintegerla fila en la tabla actor_type
kindtext, not nullqué pasó: created, status, assigned, unassigned, due, priority, moved
changestextJSON: {field: [from, to]}
created_atinteger, not nullcuándo se guardó esta fila aquí

decisions

Una elección que se tomó y vale hasta que se reemplace: por qué hacemos algo. Su evidencia — el mensaje, la fila de transcripción o el documento — son links de tipo evidence; una decisión que propuso un agente se vincula de vuelta a esa memoria con created-from.

ColumnaTipoSignificado
idinteger, PKClave primaria.
project_idinteger → projects.idel project al que pertenece
statementtext, not nullla decisión en una frase
statustext, not nullproposed, accepted, superseded, reversed
decided_atintegercuándo se tomó, según muestra la evidencia
supersedes_idinteger → decisions.idla decisión que esta reemplaza
confirmed_by_typetextquién la aceptó; null mientras está propuesta
confirmed_by_idintegerquién la aceptó; null mientras está propuesta
sourcetext, not nulldueño, agente, una importación
metadatatextJSON: lo que envía la fuente que no tiene columna y no se busca
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez
deleted_atintegerdesaparecido en la fuente; la sincronización nunca borra de verdad

Agentes y acciones

Lo que proponen los agentes y lo que hicieron: toda acción externa espera aprobación, toda llamada a una herramienta queda registrada.

proposed_actions

Algo que un agente quiere hacer fuera del almacén — responder, enviar, borrar, banear, silenciar, fijar, invitar, crear una tarea — en espera de que una persona lo apruebe. Nada externo ocurre sin aprobación.

ColumnaTipoSignificado
idinteger, PKClave primaria.
kindtext, not nullreply, send, delete, ban, mute, pin, invite, create_task, …
account_idinteger → accounts.idla cuenta que actuaría
target_typetextsobre qué actúa: message, chat, identity, task, …
target_idintegerla fila en la tabla target_type
payloadtextJSON: qué hacer, p. ej. el texto de la respuesta
reasontextpor qué lo propone el agente
statustext, not nullproposed, approved, rejected, executed, failed
proposed_by_typetext, not nullperson o bot
proposed_by_idinteger, not nullla fila en la tabla proposed_by_type
decided_by_typetextperson o bot
decided_by_idintegerla fila en la tabla decided_by_type
decided_atintegercuándo se aprobó o rechazó
executed_atintegercuándo se llevó a cabo
resulttextJSON: lo que devolvió el proveedor
errortextpor qué falló, si falló
verdicttextuseful o not_useful, según juzgó el dueño la propuesta
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

agent_actions

Cada herramienta que un agente llamó a través de las CLI o de MCP: quién, qué herramienta, con qué nivel de acceso, sobre qué. El registro de auditoría de lo que hicieron los agentes.

ColumnaTipoSignificado
idinteger, PKClave primaria.
actor_typetext, not nullperson o bot
actor_idinteger, not nullla fila en la tabla actor_type
tooltext, not nullel comando o la herramienta MCP
tiertext, not nullread, draft, write-private, write-public, destructive, admin
target_typetextel tipo de cosa a la que apunta target_id: un nombre de tabla en singular
target_idintegerla fila en la tabla target_type
statustext, not nullok, refused, failed
errortextpor qué la llamada falló o se rechazó
started_atinteger, not nullcuándo empezó la llamada
finished_atintegercuándo terminó; null mientras se ejecuta
created_atinteger, not nullcuándo se guardó esta fila aquí

Etiquetas, vínculos y búsquedas guardadas

Etiquetas y temas, los vínculos entre dos cosas cualesquiera, y las búsquedas guardadas.

tags

El nombre de una etiqueta, guardado una vez. Qué cosas la llevan está en taggings.

ColumnaTipoSignificado
idinteger, PKClave primaria.
nametext, not null, uniqueúnico entre etiquetas y temas, para que un nombre nunca sea ambas cosas
kindtext, not nulltag: una etiqueta libre; topic: de qué trata una cosa, de una lista corta que solo crea el dueño (los agentes proponen)
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

auto_tag_claims

Etiquetas que las reglas ponen a un chat al comparar su título, alias y descripción.

ColumnaTipoSignificado
chat_idinteger, not null → chats.idel chat al que pertenece
tag_idinteger, not null → tags.idla tag a la que pertenece
algorithmtext, not nullNombre y versión de las reglas que asignaron la etiqueta automática, ahora keywords-v1.
scorereal, not nullProporción de los campos de metadatos del chat (título, alias, descripción) que coincidieron con las palabras clave de la etiqueta: 1/3, 2/3 o 1; no es una probabilidad.
fieldstext, not nullLista JSON de qué campos de metadatos coincidieron, entre title, username, description.
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

Cada conexión entre dos cosas que no guarda ninguna columna. Tipos: links-to (un documento o nota enlaza a algo, tal como está escrito en él), about (una nota o documento trata de una persona, proyecto, …), member-of (un chat o persona pertenece a un proyecto u organización), labelled (una cuenta de carpeta → una etiqueta, la ruta de la subcarpeta en anchor, para que todo documento debajo lleve la etiqueta), answered-by (una tarea pregunta → el mensaje que la respondió), evidence (una decisión o memoria → su fuente), created-from (una cosa → aquello de lo que se hizo). Tipos que el almacén aún no escribe: duplicate-of (la misma pregunta hecha otra vez), related-to, assigned-to.

ColumnaTipoSignificado
idinteger, PKClave primaria.
from_typetext, not nullel tipo de cosa a la que apunta from_id: un nombre de tabla en singular
from_idinteger, not nullla fila en la tabla from_type
to_typetextel tipo de cosa a la que apunta to_id: un nombre de tabla en singular
to_idintegernull mientras el vínculo aún no nombra a nadie
kindtext, not nullla conexión; los tipos se listan en la descripción de la tabla
anchortextEl encabezado o fragmento de bloque al que apunta el vínculo dentro de su destino, como #Heading o #^block; NULL para el destino entero.
sourcetext, not nullDe dónde salió el vínculo: file (escrito en un archivo de nota), owner (añadido por el dueño) o suggested (propuesto, aún sin confirmar).
target_texttextEl destino tal como está escrito (p. ej. un nombre en una nota), guardado mientras el vínculo no apunta a nadie; hasta 500 caracteres.
target_foldedtexttarget_text normalizado en mayúsculas y acentos, sin un @ inicial, comparado con nombres y alias de personas nuevas para resolver el vínculo.
roletextEl rol que declara la relación, p. ej. un cargo en un vínculo member-of; texto libre de hasta 200 caracteres.
evidencetextTexto libre que dice por qué vale la relación (hasta 2000 caracteres).
metadatatextJSON: lo que envía la fuente que no tiene columna propia y no se busca
confirmedinteger, not null1 si el dueño respalda el vínculo, 0 si es solo una propuesta débil, sin confirmar.
created_atinteger, not nullcuándo se guardó esta fila aquí
authortextowner, agent, rule
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

searches

Cada ejecución de search messages y stats messages show, con los parámetros tal como los dio quien llama, nunca un mensaje ni un resultado. Una fila con nombre es una búsqueda guardada; una ejecución idéntica sin nombre cuenta en su fila.

ColumnaTipoSignificado
idinteger, PKClave primaria.
nametext, uniqueEl nombre único de la búsqueda guardada; NULL para una ejecución sin nombre que solo se guarda como historial.
commandtext, not nullsearch o stats.
paramstext, not nullJSON, con las claves ordenadas, para que la misma ejecución sea el mismo texto.
languagetext, not nulllucene-v1 o legacy.
versioninteger, not nullVersión del lenguaje de consultas de búsqueda usado (ahora 1).
fields_versioninteger, not nullVersión de la lista de nombres de campos buscables para la que se escribió la consulta (ahora 2).
created_atinteger, not nullcuándo se guardó esta fila aquí
last_run_atintegerCuándo se ejecutó la búsqueda por última vez (milisegundos de época); NULL para una búsqueda guardada que nunca se ejecutó.
runsinteger, not nullCuántas veces se ha ejecutado esta búsqueda.
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

taggings

Una etiqueta en una cosa.

ColumnaTipoSignificado
idinteger, PKClave primaria.
tag_idinteger, not null → tags.idla tag a la que pertenece
taggable_typetext, not nullchat, identity, message, email, document, note, person, organization, project, task, event, …
taggable_idinteger, not nullla fila en la tabla taggable_type
maininteger, not null1 en el tema principal de la cosa; como mucho uno por cosa
sourcetext, not nullde dónde salió: dueño, agente, auto, una importación
author_typetextperson o bot
author_idintegerla fila en la tabla author_type
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

Fragmentos, vectores y estado de búsqueda

Derivado: se puede reconstruir a partir de las tablas de arriba. Cada texto largo se corta en chunks; el texto de cada fragmento tiene una fila en embeddings.

conversations

Un grupo de mensajes de un chat que pertenecen a la misma discusión, de una construcción.

ColumnaTipoSignificado
idinteger, PKClave primaria.
chat_idinteger, not null → chats.idel chat al que pertenece
first_message_idinteger, not null → messages.idel message al que pertenece
buildinteger, not nullSe escribe por lotes con un número nuevo y luego pasa a ser el actual de una vez: los lectores nunca ven media construcción.
first_atinteger, not nullHora de envío del primer mensaje de la conversación (milisegundos de época).
last_atinteger, not nullHora de envío del último mensaje de la conversación (milisegundos de época).
message_countinteger, not nullCuántos mensajes tiene la conversación.
built_atinteger, not nullCuándo se ejecutó la construcción que produjo esta conversación (milisegundos de época).
algorithm_versioninteger, not nullVersión de las reglas de vinculación que agruparon los mensajes (ahora 5).
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

conversation_messages

Qué mensajes tiene cada conversación.

ColumnaTipoSignificado
conversation_idinteger, not null → conversations.idla conversation a la que pertenece
message_idinteger, not null → messages.idel message al que pertenece

conversation_state

Qué chats activó el usuario, y qué tan recientes son sus conversaciones.

ColumnaTipoSignificado
chat_idinteger, PK → chats.idel chat; una fila por chat con la agrupación activada
enabled_atinteger, not nullCuándo activó el dueño la agrupación en conversaciones para este chat (milisegundos de época).
built_atintegerCuándo se construyeron las conversaciones actuales de este chat (milisegundos de época); NULL antes de la primera construcción.
algorithm_versionintegerVersión de las reglas de vinculación de la construcción actual; NULL antes de la primera construcción.
current_buildintegerLa construcción que ven los lectores; una más alta se está escribiendo o falló.

embeddings

Un vector por modelo y texto: cualquier fragmento cuyo content_hash coincida lo usa.

ColumnaTipoSignificado
modeltext, not null&lt;provider>:&lt;model>:&lt;dims>: los vectores de modelos distintos nunca se mezclan.
content_hashtext, not nullSHA-256 en hexadecimal del texto del fragmento que recibió el modelo de vectores; el texto en sí nunca se guarda.
dimsinteger, not nullNúmero de dimensiones del vector (su longitud en float32).
vectorblob, not nullFloat32, little-endian, de longitud uno.
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

search_index_state

Hasta dónde está construido un índice de búsqueda derivado, una fila por índice. watermark es el pk de mensaje más alto cuando se creó el índice: las filas por encima las indexan los triggers, las filas hasta él los lotes que han llegado a filled_through.

ColumnaTipoSignificado
nametext, PKqué índice describe la fila, p. ej. message_words
watermarkinteger, not nullEl pk de mensaje más alto cuando se creó el índice; las filas por encima las indexan los triggers, las filas hasta él el llenado por lotes.
filled_throughinteger, not nullEl pk de mensaje más alto que ha indexado hasta ahora el llenado por lotes; el índice está completo cuando llega a la marca.
terms_throughinteger, not nullEl pk de mensaje más alto cuyas palabras están en el vocabulario de corrección de erratas; 0 significa que el vocabulario no está construido.
normalizer_versioninteger, not nullVersión de las reglas de normalización de texto con que se construyó el índice.
built_atintegerCuándo terminó de llenarse el índice (milisegundos de época); NULL mientras aún se llena.
analyzertextLas opciones del extractor de raíces y la versión de Snowball que construyeron la fila de raíces (analyzerIdentity); NULL hasta que un llenado la reclama.

search_terms

Cada palabra del índice de búsqueda de mensajes, para corregir erratas.

ColumnaTipoSignificado
termtext, PKla palabra tal como se indexó
lengthinteger, not nullNúmero de caracteres de la palabra, usado para encontrar candidatas a errata de longitud parecida.

search_term_trigrams

Fragmentos de tres letras de cada palabra de búsqueda, para encontrar palabras que se parecen a una mal escrita.

ColumnaTipoSignificado
trigramtext, not nullUn fragmento de tres caracteres de una palabra conocida, usado para encontrar palabras que se parecen a una mal escrita.
lengthinteger, not nullLongitud en caracteres de la palabra de la que sale el trigrama.
termtext, not nullLa palabra de búsqueda conocida a la que pertenece el trigrama (los números no tienen trigramas).

involvements

Quién participó en qué, y cuándo: una fila por persona o identidad por mensaje, correo, reunión, tarea o documento. Derivado de remitentes, destinatarios, participantes, asignados y vínculos, y se reconstruye cuando se quiera; convierte «todo sobre Alex» en un solo rango indexado.

ColumnaTipoSignificado
idinteger, PKClave primaria.
person_idinteger → persons.idnull mientras la identidad no está vinculada a nadie
identity_idinteger → identities.idla identity a la que pertenece
subject_typetext, not nullmessage, email, meeting, task, document, note, …
subject_idinteger, not nullla fila en la tabla subject_type
roletext, not nullsender, recipient, participant, assignee, author, mentioned, linked
occurred_atinteger, not nullcuándo ocurrió el sujeto
scopetext, not nullpersonal o work, según la cuenta, el chat o el proyecto del sujeto
account_idinteger → accounts.idla cuenta de integración por la que llegó
project_idinteger → projects.idel project al que pertenece
created_atinteger, not nullcuándo se guardó esta fila aquí

involvement_pending

Cosas cuyas filas de involvements están desactualizadas: un mensaje, chat, reunión, correo, tarea o cualquier cosa de la que parte un vínculo. Los triggers las encolan; el vaciado recalcula las filas de esa cosa.

ColumnaTipoSignificado
idinteger, not nullLa fila que espera ser indexada.
indexable_typetext, not nulla qué tabla pertenece la fila en espera

chunks

Fragmentos de un texto más largo, la unidad que recibe un vector: tramos de un documento, un correo, el texto de un adjunto, una nota, una transcripción o un resumen de reunión; una tarea o evento corto es un solo fragmento. Una conversación de mensajes también se corta en fragmentos aquí, una fila conversation por fragmento, y chunk_messages dice qué mensajes abarca cada fragmento; así una sola búsqueda puede leer todo tipo de texto, filtrado por ámbito, cuenta, proyecto y tiempo.

ColumnaTipoSignificado
idinteger, PKClave primaria.
chunkable_typetext, not nulldocument, email, attachment, note, memory, conversation, meeting_transcript, meeting_summary, event, task
chunkable_idinteger, not nullla fila en la tabla chunkable_type
positioninteger, not nullorden dentro de su padre, desde 0
start_offsetinteger, not nulldónde empieza el fragmento en el texto del padre, en caracteres
end_offsetinteger, not nulldónde termina, sin incluirlo
content_hashtext, not nullhash del texto del fragmento; su vector es la fila de embeddings con este hash, así que un texto igual se vectoriza una vez
scopetextcopiado de la cuenta, el chat o el proyecto del padre, para que una búsqueda vectorial filtre antes de comparar; los triggers siguen los cambios de un chat o una cuenta
account_idinteger → accounts.idcopiado del padre, un filtro para la búsqueda vectorial
project_idinteger → projects.idcopiado del padre cuando pertenece a uno
occurred_atintegercuándo ocurrió el padre (enviado, celebrado, escrito), un filtro para la búsqueda vectorial
created_atinteger, not nullcuándo se guardó esta fila aquí
updated_atinteger, not nullcuándo cambió esta fila aquí por última vez

chunk_messages

De qué mensajes se corta el fragmento de una conversación. Una fila por cada fila conversation de chunks; borrar cualquiera de los mensajes borra el fragmento.

ColumnaTipoSignificado
chunk_idinteger, PK → chunks.idel fragmento, de tipo conversation
first_message_idinteger, not null → messages.idel message al que pertenece
last_message_idinteger, not null → messages.idel message al que pertenece
text_startintegerdónde empieza el fragmento dentro del texto del primer mensaje, cuando empieza a mitad de mensaje
text_endintegerdónde termina dentro del texto del último mensaje

Almacén

Contabilidad interna del propio archivo.

schema_migrations

Qué migraciones ha aplicado este archivo.

ColumnaTipoSignificado
versioninteger, PKel número de la migración
min_compatibleinteger, not nullLa versión de esquema más antigua cuyo código aún puede escribir con seguridad un archivo en esta versión; una compilación más antigua rechaza el archivo.
applied_atinteger, not nullCuándo se aplicó esta migración al archivo (milisegundos de época).

store_settings

Ajustes del propio archivo del almacén, compartidos por todos los perfiles, tg y MAX, a diferencia del archivo de configuración de un perfil.

ColumnaTipoSignificado
keytext, PKel nombre del ajuste
valuetext, not nullEl valor del ajuste como texto, compartido por todos los perfiles y mensajerías que usan este archivo de almacén.
atinteger, not nullCuándo se escribió el ajuste por última vez (milisegundos de época).

Para ver estas tablas en acción, lee cómo funciona la búsqueda; para ver cómo encaja el almacén en las herramientas, lee arquitectura.