Documentación técnica de Memories
Este documento describe el almacenamiento implementado actualmente, los límites de confianza, las autorizaciones locales, el Center alojado, los secretos sellados, el flujo de datos de recuperación, la sincronización de objetos en la nube y los límites del estado de escritorio. Describe el mismo comportamiento que SECURITY.md, docs/architecture.md, docs/authorization.md y docs/center.md. La versión del formato de almacenamiento es 1. Este software está en desarrollo; superar las pruebas no equivale a una auditoría de seguridad independiente.
Almacenamiento y límites de confianza
Las tablas de la base de datos local son header, state y checkpoints. Salvo los metadatos de formato, la sal y los números de fila, los valores son texto cifrado con datos asociados. El registro también contiene texto cifrado. No hay un índice de texto completo persistente en texto plano.
El campo version de la cabecera de formato debe ser 1; de lo contrario, la apertura falla. La contraseña del usuario deriva una clave de 32 bytes mediante Argon2id (versión 0x13, 64 MiB de memoria, 3 iteraciones, paralelismo 1) y una sal de 16 bytes. Esta clave envuelve una clave maestra aleatoria, con memories/master/v1 como datos asociados. La clave maestra cifra el estado y los puntos de control locales. El cifrado simétrico usa XChaCha20-Poly1305.
Cada época de permisos tiene su propia clave de bóveda. Cada revisión tiene una clave de datos aleatoria, envuelta por la clave de esa época. El contenido serializado se divide en bloques de 256 KiB autenticados por separado; la posición del bloque y el número total de bloques forman parte de los datos asociados. La firma de la revisión cubre el ID del recurso, las revisiones padre, la cabecera de política, la marca de eliminación, el texto cifrado y el certificado del dispositivo. El algoritmo de firma es Ed25519.
Los cambios se preparan primero en un estado clonado; después se confirman el estado cifrado y los puntos de control en una misma transacción SQLite, con synchronous=FULL. Las intenciones de lectura y ejecución se confirman antes de la entrega. Por ello, un fallo de disco impide la entrega; un fallo tras confirmar la intención puede dejar un resultado desconocido. Un bloqueo exclusivo del sistema operativo limita cada directorio de datos a un escritor cooperativo. La inicialización termina de escribir la base de datos en el mismo directorio, la cierra y sincroniza, y después la publica en la ubicación de destino sin sobrescribir un destino existente. Cada dispositivo usa su propia base de datos. Entregar un archivo SQLite en uso a un cliente de almacenamiento en la nube para sincronizarlo no ofrece seguridad transaccional entre dispositivos.
La clave Ed25519 del usuario certifica la clave de firma Ed25519 y la clave de intercambio X25519 del dispositivo. El certificado por sí solo no basta: la política de cada bóveda también debe autorizar explícitamente al dispositivo. Las claves de distintos dispositivos del mismo usuario son independientes. La capacidad inicial de firma de usuario solo se entrega a dispositivos personales aprobados mediante un paquete de aprobación autenticado y cifrado para el destinatario. Tras revocar un dispositivo, la clave de identidad del usuario no puede eludir la lista de dispositivos permitidos de esa bóveda.
El sobre de transporte contiene la versión de formato, la clave del dispositivo emisor, la clave de intercambio del destinatario, una clave pública X25519 efímera, la carga AEAD y una firma Ed25519. La clave de transporte se deriva con HKDF. Se autentican la identidad del destinatario y la clave efímera. La incorporación de dispositivos usa solicitudes firmadas que caducan y fija explícitamente la clave pública del dispositivo que aprueba. La solicitud solo se consume tras una confirmación correcta. La huella usada para aprobar es el SHA-256 completo. Los valores abreviados de las listas no bastan por sí solos para aprobar.
La política es un historial lineal firmado que contiene miembros, roles, listas de dispositivos permitidos, un conjunto de revocaciones que solo crece y épocas. Las comprobaciones de roles usan la política anterior. Los usuarios normales pueden autorizar otro dispositivo para su propia identidad sin cambiar la pertenencia. Solo Admin u Owner pueden invitar miembros, aprobar incorporaciones y autorizar dispositivos para miembros. Admin puede modificar miembros Admin, Editor y Reader, pero no convertir a nadie en Owner, modificar un Owner existente, revocar dispositivos ni transferir la propiedad. Owner sí puede. La transferencia de propiedad mantiene exactamente un Owner. La validación de políticas rechaza los cambios de Admin sobre miembros Owner o el conjunto de revocaciones.
El historial de recursos es un grafo acíclico dirigido direccionado por contenido. Un recurso está en conflicto cuando tiene varias revisiones aún no consumidas. Una revisión de resolución debe nombrar todas las revisiones padre visibles. Las marcas de eliminación retiran el recurso de la vista actual, pero no borran el historial.
Las copias de seguridad guardan el estado local firmado y el material de recuperación bajo un sobre independiente de Argon2id y AEAD. La recuperación genera nuevas claves de dispositivo y nuevos ID de bóveda, conserva el contenido actual y las cabeceras en conflicto, y coloca el historial firmado original en un archivo cifrado de solo lectura. La recuperación no afirma que siga siendo válida la pertenencia compartida anterior. Las bóvedas exclusivas del dispositivo, las autorizaciones de nube y las colas de envío y recepción de nube no se incluyen en las copias de seguridad.
El diseño protege frente a lo siguiente: que el relé lea o falsifique contenido de recursos; la sustitución de la identidad del par después de comprobar explícitamente las huellas; la modificación de texto cifrado autenticado; la lectura de una base de datos copiada sin la contraseña local; que un lector falsifique escrituras; que un administrador cambie la propiedad; que un dispositivo revocado use la clave de identidad del usuario para emitirse una nueva autorización de dispositivo; que CLI o MCP impriman credenciales accidentalmente, acepten contraseñas en la línea de comandos o permitan que capacidades MCP hereden la elevación del terminal; modificaciones no detectadas de revisiones firmadas o auditorías, huecos en las cadenas y truncamiento de puntos de control respecto al estado restante de la base de datos.
Los siguientes casos quedan fuera de estos límites y la documentación no los presenta como resueltos:
- Terminales comprometidos, administradores del sistema operativo, programas maliciosos autorizados, inspección de memoria, registro de pulsaciones y copia intencional de texto plano por el usuario. Los búferes de claves propiedad de Rust se ponen a cero. No se garantiza el borrado de la memoria de intercambio del sistema operativo, los volcados de fallos, las asignaciones de dependencias ni las cadenas recolectadas por el recolector de basura de Dart. El escritorio no tiene almacenamiento de claves por hardware.
- El relé puede observar metadatos de tráfico, bloquear conexiones, registrar texto cifrado por su cuenta, retrasar revocaciones o separar dispositivos. El servidor de relé incluido en el repositorio no escribe recursos, pero no se puede obligar a un servidor malicioso a no registrar tráfico. El relé no mantiene colas para dispositivos desconectados.
- La revocación sin conexión no puede borrar texto plano, claves o copias de seguridad anteriores. Los terminales que todavía no hayan recibido la revocación pueden seguir usando sus copias locales antiguas.
- La auditoría demuestra el contenido firmado y su continuidad respecto a un estado conocido, no que un dispositivo comprometido haya registrado cada acceso. Sustituir toda la base de datos y la evidencia local por una copia más antigua pero internamente coherente no puede detectarse sin un punto de control más reciente de otro dispositivo o un anclaje externo. No hay un servicio de sellado de tiempo de confianza.
- Los demás procesos del mismo usuario del sistema operativo están dentro del límite de la cuenta local. IPC autentica al usuario del sistema operativo. La elevación del terminal usa además el PID del proceso padre. Esto no aísla frente a procesos maliciosos del mismo usuario ni proporciona una identidad de sesión persistente inmune a la reutilización de PID.
- Las huellas de ejecutables se comprueban antes del inicio. No hay aislamiento del sistema operativo, firma de código obligatoria, ejecución atómica mediante identificadores de archivo ni contención de procesos descendientes.
- Las copias al portapapeles, los archivos exportados y las credenciales que el usuario solicita copiar explícitamente salen de la bóveda cifrada según sus acciones. El contenido copiado permanece después del bloqueo, y el historial del sistema operativo u otras aplicaciones pueden conservarlo.
IPC local y autorizaciones
service::Request es la interfaz compartida de operaciones tipadas, diferenciadas por op en snake_case. Se rechazan los campos de nivel superior desconocidos. IPC local usa tramas JSON con un prefijo de longitud de 32 bits en big-endian y un envoltorio de versión 1; el receptor HTTP/WebSocket opcional y RPC por relé comparten tramas JSON binarias WebSocket (con autenticación por token). El acceso remoto de escritorio ofrece las mismas operaciones que IPC local después del desbloqueo o la elevación (ws:remote / relay:remote); FFI/Share móvil mantiene listas de denegación por plataforma. Véanse docs/remote-daemon.md y SECURITY.md. El centro de autorización opcional ([[centers]]) impide la inicialización local de autorizaciones. El modo de tickets emite tickets de registro, autorización MCP y desbloqueo; el modo alojado guarda el contenido en la bóveda cifrada del servidor Center. Véase lo siguiente, además de docs/center.md y docs/authorization.md.
El daemon solo atiende al usuario actual del sistema operativo. Windows usa canalizaciones con nombre; Linux y macOS usan sockets Unix. IPC acepta como máximo 16 clientes simultáneos. La lectura de tramas en canalizaciones con nombre de Windows sigue siendo bloqueante: los clientes del mismo usuario que se atasquen ocupan esas plazas, pero un solo cliente atascado o una transferencia de nube no bloquea todas las demás conexiones. La E/S de tramas Unix tiene plazos límite. Las operaciones de servicio que mantienen el bloqueo de escritura, incluida la ejecución de subprocesos de confianza, siguen siendo secuenciales.
El desbloqueo normal caduca tras 15 minutos de inactividad. sudo usa la misma contraseña local, dura como máximo 15 minutos, caduca tras 5 minutos de inactividad y se limita al proceso padre del terminal que emite la orden. Bloquear o reiniciar elimina la elevación. Los intentos con el sistema completamente bloqueado están sujetos a límites de frecuencia, pero no se escriben en la auditoría firmada persistente. Con el sistema desbloqueado y una identidad de firma local disponible, las operaciones fallidas se auditan. La intención se confirma antes de entregar; un fallo repentino deja una intención confirmada, no un resultado inventado.
Una autorización MCP es una capacidad local al portador que se escribe en un archivo indicado por el llamante y no se imprime en el terminal. --minutes de mcp grant determina la vigencia; solo --write permite crear memorias normales. mcp serve --grant-file lee la capacidad de ese archivo y ofrece herramientas mediante MCP 2024-11-05 sobre stdio: memory_search, memory_retrieve, memory_ask, memory_read, memory_read_revision, memory_history, memory_diff, memory_write, memory_delete, card_write, card_graph, card_link. Cada llamada incluye la bóveda de la autorización y comprueba individualmente la capacidad antes de su despacho.
MCP no puede heredar la elevación del terminal. No puede leer memorias privadas, archivos ni credenciales, ejecutar procesos, sesiones remotas, proxies de bucle local ni trabajos criptográficos, gestionar miembros de bóvedas ni solicitar DesktopStatus. El bloqueo elimina las autorizaciones de memoria; las no caducadas se restauran al desbloquear, y el bloqueo por sí solo no las borra. Las herramientas MCP pueden invocar emisión, listado, revocación, solicitud y recogida del servicio de autorizaciones, pero siguen usando la propia capacidad MCP, sin heredar elevación del terminal ni usar el bearer de administrador del Center. Las lecturas normales no resuelven {{secret:标签}}. card_write no lleva mapas de secretos, de modo que actualizar tarjetas con referencias a secretos falla en la validación. Los ID cortos de referencias solo abrevian los ID tipados de credenciales; los marcadores del cuerpo permanecen iguales.
otp_code implementa TOTP de RFC 6238 y HOTP de RFC 4226. HOTP guarda el contador incrementado en la misma confirmación que devuelve el código. parse_otp_import acepta otpauth:// y otpauth-migration://offline?data=... de Google Authenticator y convierte las cuentas en tarjetas TOTP o HOTP. Si el tipo está indicado en el host del URI, el parámetro type o los datos de migración, se usa ese valor; si no, una cuenta con contador es HOTP y las demás son TOTP. El llamante no necesita seleccionar el tipo por separado. --image de la línea de comandos primero decodifica estos dos tipos de URI desde la imagen con rqrr y después sigue la misma ruta de importación; no se pueden proporcionar simultáneamente un URI y --image. Para varias tarjetas, --title solo sirve de prefijo de título, y --id solo puede sustituir una tarjeta. La cámara del móvil no importa estos dos tipos de QR OTP. El escaneo para emparejar dispositivos alojados es una ruta distinta, descrita más adelante. Las revisiones de tarjetas también pueden incluir alias, notas y categorías opcionales; omitir estos campos al actualizar conserva sus valores, mientras que una cadena vacía los borra. Las semillas no entran en búsqueda ni MCP. TOTP depende de que el reloj local sea correcto. El resultado generado es un código temporal autorizado, no una exportación de la semilla; la auditoría no registra códigos ni semillas.
credential_copy es una excepción explícita a las restricciones de salida de credenciales. Exige elevación local, confirma primero la intención de auditoría y después entrega el texto plano UTF-8 al cliente de portapapeles. CLI solo imprime {"copied":true} tras escribir correctamente en el portapapeles del sistema. MCP no puede solicitar copias. La auditoría registra credential.copy y la intención de entrega, no una confirmación de éxito del portapapeles del sistema operativo.
La ABI móvil se declara en crates/ffi/memories.h. Los identificadores son ID numéricos registrados, no punteros Rust sin procesar. Las cadenas devueltas se liberan una vez con memories_free. Un JSON inválido produce un error genérico sin repetir la entrada. memories_lock_all avanza la generación global de bloqueo cuando la aplicación pasa a segundo plano y suprime respuestas tardías en curso, además de descartar todas las sesiones alojadas. La ruta móvil no incluye ejecución de procesos, creación de autorizaciones MCP locales, gestión de autorizaciones locales ni RPC de solicitudes de permisos. Las llamadas hosted_* que conectan con un Center alojado son una ruta distinta: el contenido solo permite listar, leer y escribir kind = credential.
Los trabajos criptográficos comprueban el resumen de aprobación antes de resolver los ID cortos, por lo que el resumen queda vinculado a las referencias que vio el llamante. El servicio comprueba la elevación local y el acceso a la bóveda, resuelve únicamente recursos de credenciales, confirma la intención de ejecución y después llama al ejecutor compartido. El ejecutor vuelve a comprobar las herramientas, copia y verifica las entradas, materializa las credenciales en un espacio de trabajo accesible solo por su propietario, ejecuta órdenes sin shell, suprime la salida de las herramientas y publica solo los artefactos correctos. Los marcadores solo sustituyen rutas. La lista de permitidos de MCP y FFI móvil rechazan los trabajos de procesos.
Autorizaciones, solicitudes de permisos, alojamiento y secretos sellados
Las autorizaciones locales y el Center alojado usan los mismos límites por rol. Reader tiene como máximo read, Editor read_write, Admin read_write_delete y Owner allow_all. El ámbito omitido es read. Reader y Editor no pueden emitir ni delegar. La emisión está limitada tanto por el rol como por el ámbito de la autorización del llamante; no puede cruzar bóvedas ni durar más que la autorización padre. La duración es de 1–60 minutos. La emisión directa por un miembro tiene profundidad 1; emitir usando una autorización añade 1 y se rechazan profundidades superiores a 2. Las credenciales persistentes de miembros en Center tienen profundidad 0 y no cuentan como delegación. El destinatario ya debe ser miembro de la bóveda, su rol no puede superar el del emisor y no puede usar el nombre reservado center-admin. La autorización de contenido no cambia el rol del destinatario.
Puede haber como máximo 10000 autorizaciones vigentes simultáneas (service::MAX_ACTIVE_GRANTS); el daemon local y el Center alojado comparten este límite. Los tokens aparecen únicamente en la respuesta de emisión o recogida. El estado persistente solo guarda SHA-256 y metadatos, y las comparaciones se hacen en tiempo constante. El bloqueo descarta las claves de memoria y suspende las autorizaciones sin revocarlas; las no caducadas siguen siendo válidas después de desbloquear o reiniciar. Las autorizaciones caducadas y sus descendientes se eliminan durante la carga y las comprobaciones periódicas. La revocación se propaga a los descendientes. Si se elimina un miembro o el rol de un emisor baja por debajo del ámbito emitido, las autorizaciones correspondientes quedan invalidadas al confirmar la política. Las autorizaciones no entran en la sincronización de bóvedas ni en las copias de recuperación.
Las solicitudes de permisos se aprueban antes de recogerse. Aprobar una solicitud de ámbito solo registra sus límites, sin crear un token; el solicitante lo recoge una sola vez con las credenciales de miembro usadas al crear la solicitud. Si esa respuesta se pierde, el token no se puede recuperar de nuevo. Las solicitudes de rol solo existen localmente y, al aprobarse, cambian inmediatamente la política sin recogida; el rol Owner usa una transferencia de propiedad firmada, y una autorización temporal no puede aprobar cambios permanentes de rol. El Center alojado solo acepta solicitudes de ámbito. Los solicitantes no pueden aprobar ni rechazar sus propias solicitudes. Los llamantes autorizados cuyo sujeto difiere del emisor pueden presentar solicitudes, pero no aprobarlas, rechazarlas, cancelarlas ni recogerlas. El límite de pendientes es de 20 por solicitante y bóveda y 200 por bóveda. Caducan después de 7 días. Las solicitudes decididas, caducadas o recogidas se eliminan 30 días después de su última transición.
La auditoría local es una cadena de hashes firmada por dispositivo. DIR/audit.jsonl del Center es una cadena sin clave: detecta modificaciones respecto a una cabecera conocida, pero no impide que el operador reescriba todo el registro.
Center tiene dos modos. mode = ticket (predeterminado) solo emite tickets de registro, autorización MCP y desbloqueo; el contenido permanece en la bóveda cifrada de cada dispositivo. Los tickets de desbloqueo se pueden reutilizar hasta que caduquen, no están vinculados a un dispositivo concreto y solo permiten el desbloqueo local con la contraseña del dispositivo, sin conceder elevación sudo ni MCP. Con mode = saas y Center ejecutado con --data, el contenido está en la bóveda cifrada del servidor. El operador posee la contraseña de la bóveda y puede leer el texto plano desbloqueado. Se trata de cifrado en el servidor y no de un límite de confidencialidad frente al operador. Cuando hay exactamente un mode = "saas" en la configuración, el daemon dirige el RPC de contenido a /v1/rpc de ese Center. Las operaciones no compatibles fallan directamente, sin recurrir a la bóveda local. El bearer de administrador gestiona bloqueo, desbloqueo y miembros; usarlo en rutas de contenido devuelve 401. allow_all solo cubre el contenido alojado y no incluye administración del servidor, gestión de dispositivos, sudo, registro, recuperación, ejecución ni trabajos criptográficos.
Las tarjetas con e2e: true en bóvedas alojadas rechazan secretos en texto plano. Tras el emparejamiento, los secretos se colocan en sobres dirigidos a la clave pública X25519 del dispositivo y firmados por una clave Ed25519 conocida. Center solo guarda claves públicas y texto cifrado. Puede ver quién, qué tarjeta y cuándo, y también retener o reproducir sobres antiguos, pero no puede ver el cuerpo. Las autorizaciones de dispositivo no pueden emitir ni aprobar. La revocación elimina los sobres de ese dispositivo, pero no puede recuperar el texto plano ya descifrado. Solo una autorización de Owner puede quitar la marca e2e, y esa escritura no puede incluir secretos. La incorporación de nuevos dispositivos a bóvedas locales sigue usando solicitudes firmadas que caducan y la comprobación de huellas completas, sin cámara.
Recuperación y flujo de datos de modelos
La caché de búsqueda conserva índices de como máximo dos bóvedas. Cada bóveda admite hasta 10,000 fragmentos, 16 MiB de texto fuente y metadatos y 32 MiB de vectores. Se excluyen antes de indexar el contenido privado, las credenciales, los archivos y las revisiones eliminadas, en cuarentena o en conflicto. El almacenamiento temporal de SQLite se fuerza a memoria. La caché no entra en copias de seguridad ni exportaciones a la nube. Bloquear vacía todos los índices y vectores. Los cambios de política, revisiones o cuarentena invalidan la caché correspondiente.
Los cuerpos normales se dividen cerca de límites seguros de Unicode en fragmentos de hasta 768 caracteres, normalmente con un solapamiento de 128. El chino y el texto mixto se segmentan con Jieba. Los pesos de FTS5 BM25 para título, cuerpo y metadatos seguros son 5, 1 y 2. any combina palabras clave, all exige todas las palabras y phrase exige la frase original. Estas restricciones también filtran los candidatos vectoriales e híbridos. Las consultas se escapan y no se ejecutan como operadores FTS arbitrarios. memory search básico combina fragmentos por documento; memory_retrieve y rag search devuelven fragmentos individuales con ID de recurso, revisión, hash estable de fragmento, desplazamientos UTF-8 originales, puntuaciones y etiquetas de cita.
Los vectores son una caché normalizada en memoria. La recuperación vectorial usa similitud coseno. La recuperación híbrida usa fusión de rangos recíprocos, con k igual a 60. La reordenación ligera predeterminada mejora la cobertura de la consulta y la coincidencia exacta de frases en un conjunto limitado de candidatos. Un endpoint de modelo configurado puede realizar reordenación aprendida.
El modelo de embeddings predeterminado es EmbeddingGemma 300M Q4 dentro del proceso, con inferencia ONNX local y vectores de dimensión 768. La telemetría ONNX se desactiva explícitamente antes de crear la sesión de inferencia. El motor de inferencia se incluye con la aplicación; los archivos del modelo, de aproximadamente 209 MiB, son datos públicos que rag model-install descarga de una revisión fija del repositorio y cuyo SHA-256 se verifica archivo por archivo antes de publicarlos, o que se suministran mediante rag.local_model_dir. Los archivos verificados se pueden reutilizar sin conexión. Tienen una licencia Gemma independiente; no son secretos ni un límite de seguridad auditado de forma independiente.
Tras configurar una dirección remota de embeddings, las operaciones RAG autorizadas pueden enviar todos los fragmentos de documentos aptos a ese endpoint. La generación solo envía la pregunta y los fragmentos fuente seleccionados. La reordenación aprendida envía sus candidatos. Las URL remotas deben usar HTTPS; HTTP solo se permite en bucle local. Se rechazan las redirecciones de API de modelos. Las solicitudes de bucle local no pasan por proxies. Las demás pueden usar proxies HTTP, HTTPS o SOCKS y la configuración de proxy del entorno. Los reintentos son limitados y solo cubren fallos transitorios de conexión o lectura, HTTP 429 y determinados 5xx. Los reintentos pueden generar cargos repetidos. No se desactiva la validación TLS. Las claves API solo se referencian mediante nombres de variables de entorno en la configuración; no se escriben en TOML, URL ni argumentos de órdenes. Los parámetros de herramientas MCP no pueden elegir URL de proveedores, credenciales ni proxies.
Las bóvedas exclusivas del dispositivo rechazan antes de la inferencia los pasos de modelo destinados a proveedores fuera del bucle local. La inferencia local y los servicios de bucle local configurados explícitamente siguen disponibles.
Retrieve, RagIndex, RagStatus y RagAsk conservan la autorización de bóveda y los ámbitos MCP. IPC realiza el trabajo de modelos fuera del mutex del servicio y vuelve a comprobar la generación de desbloqueo, las autorizaciones, el acceso y las marcas de revisión fuente antes y después del trabajo externo y antes de entregar. La intención firmada precede a la inferencia o exportación. La auditoría registra éxito o fallo y los ID de fuentes entregadas, sin registrar prompts ni claves. La generación trata el texto fuente como datos no fiables y no tiene herramientas de aplicación. El modelo debe devolver una respuesta estructurada con citas. Se rechazan los ID de citas inexistentes. Sin evidencia no se invoca la generación y el resultado se marca insufficient_evidence. La validación de citas solo comprueba que existan; no demuestra la exactitud factual de la prosa generada ni elimina la inyección de prompts en fuentes no fiables.
El bloqueo, las autorizaciones caducadas o revocadas y los cambios del estado de las fuentes suprimen resultados tardíos e impiden pasos posteriores. Las solicitudes remotas o inferencias ya iniciadas pueden terminar, y no se puede retirar el texto remoto ya enviado.
FFI móvil recibe la búsqueda léxica mejorada y admite BM25 retrieve. La configuración de modelos y la interfaz de inferencia no se han añadido a Flutter. Las operaciones basadas en modelos usan el daemon de escritorio configurado.
Sincronización de objetos en la nube
CLI de escritorio usa PKCE, callbacks de bucle local y endpoints fijos de proveedores para OAuth en el navegador. CloudBegin, bajo sudo, crea un ticket que caduca y está vinculado al llamante, proveedor y cliente. Las solicitudes de red se realizan fuera del daemon. CloudComplete comprueba el ticket y la autorización actual antes de confirmar. Bloquear, cerrar sesión o reiniciar invalida los tickets pendientes para evitar que resultados tardíos restauren el inicio de sesión.
State.cloud_accounts guarda los tokens cifrados localmente. El estado solo devuelve metadatos de las cuentas. Copias de seguridad, emparejamiento, sincronización de bóvedas y MCP no incluyen tokens. Iniciar sesión no establece pertenencia a una bóveda. Cada proveedor conecta una cuenta por dispositivo; volver a iniciar sesión solo sustituye la cuenta de ese proveedor después de completar la nueva autorización.
State.cloud_sync guarda la bandeja de salida persistente y los recibos de entrada en el mismo estado cifrado. CloudSyncEnqueue escribe los bytes exactos del sobre serializado y los descriptores firmados antes de cualquier E/S de transporte. El ID del objeto es el SHA-256 de esos bytes y los reintentos reutilizan ese ID. CloudSyncWork devuelve texto cifrado y cursores de listado, sin tokens OAuth. sync::execute realiza cargas, descargas y listados acotados sin mantener el mutex del servicio. CloudSyncAck comprueba la generación de sesión local al proceso y después confirma conjuntamente marcas de carga, ID descubiertos, bytes descargados y la fusión de la bóveda. Si un descriptor llega antes que el objeto, queda pendiente. Bloquear, desbloquear y cerrar sesión incrementan la generación de sesión para que las confirmaciones tardías no puedan importar.
memories cloud sync hace que el daemon actualice los tokens y cargue y descargue mediante las carpetas de aplicación de OneDrive o Google Drive. Este HTTP se ejecuta fuera del bloqueo de escritura. Los tokens nunca se devuelven por IPC. Las pruebas usan MemoryTransport y entornos de prueba Graph/Drive en bucle local. Las cargas de colas completadas se compactan en recibos hash y marcas de publicación por proveedor y destinatario. Los recibos permanecen localmente y no borran el historial en la nube. Los objetos ausentes se reintentan con una espera exponencial persistente. La capacidad pendiente aplica contrapresión al listado. Los trabajadores de proveedores se ejecutan secuencialmente por cuenta y rechazan resultados de actualización o importación de sesiones invalidadas.
Por tanto, la autorización CLI y cloud sync están implementados, y el transporte de proveedores se ha probado con entornos locales. El consentimiento, la actualización, la convergencia entre dos dispositivos, los reintentos sin conexión y la revocación en cuentas reales de OneDrive o Google Drive todavía no se han entregado como comportamiento verificado. Los controles móviles de inicio de sesión y sincronización usan AppAuth y el trabajador Rust compartido; el consentimiento real y la validación de plataforma siguen siendo requisitos para publicar. La sincronización móvil en segundo plano no está habilitada.
La revocación descarta las exportaciones a la nube en cola e invalida el trabajo capturado antes de la siguiente operación de objetos. Las solicitudes de red ya iniciadas no se pueden retirar.
La sincronización explícita entre dispositivos es otra ruta. sync export y sync import intercambian sobres autenticados completos. Las operaciones en línea sync send y sync receive entregan el mismo tipo de paquetes al relé sin estado. Un envío correcto solo significa que el relé recibió el paquete. Las escrituras desconocidas de épocas antiguas entran en cuarentena y solo pueden volver a firmarse con sync reapply después de revisarlas localmente. Una bifurcación de permisos exige que alguien que sea propietario en ambas ramas firme la cabecera seleccionada y toda la cadena de políticas descartada. Las transferencias de propiedad incompatibles siguen bloqueadas.
Límites del estado de escritorio
Request::DesktopStatus devuelve el estado de inicialización y bloqueo, recuentos de bóvedas y conexiones, tipos de proveedores configurados y recuentos de colas de sincronización. Se ejecuta antes del despacho de operaciones desbloqueadas, no clona ni confirma el estado cifrado, no toca temporizadores de inactividad o elevación y no expone identificadores, resúmenes de cuentas, contenido ni credenciales. Las respuestas estando bloqueado no contienen estos detalles. La lista de permitidos de MCP rechaza esta solicitud.
La biblioteca CLI alberga el panel local y las bandejas de Windows y macOS. memories tray y el ejecutable independiente memories-tray usan bucles de eventos nativos en el hilo principal. El servicio HTTP y los sondeos de estado acotados se ejecutan en hilos separados, de modo que un daemon ocupado no bloquea la bandeja ni el navegador. Los sondeos invocan CLI del mismo directorio mediante IPC normal autenticado por el sistema operativo, tienen plazos límite y limpian los subprocesos. El plazo del sondeo para lecturas de canalizaciones Windows es de tres segundos. Si falla el sondeo se borran los detalles; el bloqueo oculta los detalles en el siguiente sondeo. El sondeo no renueva la inactividad de desbloqueo ni la elevación.
La superficie HTTP solo ofrece recursos integrados y una proyección fija del estado; no puede despachar solicitudes de servicio arbitrarias. Solo escucha en 127.0.0.1. El único endpoint de datos es GET /api/status, protegido por un token aleatorio de 256 bits generado en cada proceso. El lanzador coloca el token en el fragmento de la URL. La página lo elimina de la barra de direcciones, lo conserva únicamente en el almacenamiento de sesión de la pestaña y lo envía en la cabecera Authorization. La URL de inicio completa es una capacidad del panel y no debe compartirse. Se rechazan valores Host inesperados, Origin ajenos y metadatos de obtención entre sitios. No hay CORS, recursos de terceros, incrustación en marcos ni rutas de modificación. El navegador recibe una proyección de estado tipada, no un puente IPC genérico, credenciales, cuerpos de memorias, nombres de cuentas, rutas ni tokens de autorización.
La bandeja puede iniciar el daemon local mediante una acción explícita del menú. Cerrar la bandeja o el panel detiene su receptor HTTP y supervisión, sin detener ni desbloquear un daemon independiente. La autenticación sigue realizándose en CLI. Los programas maliciosos de la misma cuenta del sistema operativo siguen dentro del límite de confianza local existente.
La compilación Linux incluye memories webui, con los mismos límites de panel de bucle local y token. El bucle nativo de eventos de la bandeja solo se compila en Windows y macOS. Linux no tiene bandeja nativa.
El TOML local solo contiene ajustes no secretos de almacenamiento, relé y escritorio. Los archivos explícitamente ausentes, las claves desconocidas y los valores malformados se rechazan antes de abrir la bóveda. Las rutas de almacenamiento relativas se resuelven respecto al archivo de configuración. Cambiar la ruta selecciona otra bóveda y no migra datos. Las URL del relé mantienen las restricciones TLS remotas existentes y no pueden incluir credenciales.