Memories / Documentación

En esta página

Memories

Cliente Android/iOS para Memories. La interfaz Flutter llama al servicio Rust compartido mediante crates/ffi/memories.h; no implementa un protocolo separado de almacenamiento o criptografía.

Elegir un modo

En el primer inicio, incluido el primero después de actualizar desde una versión sin preferencia de modo, elija dónde quiere trabajar:

Modo Ubicación de los datos Qué necesita
Standalone Biblioteca cifrada en este teléfono; funciona sin conexión Crear una biblioteca local o desbloquear la existente
Center El almacén alojado de su servidor propio Un origen de servidor como https://center.example.com y un token de miembro
SaaS El almacén alojado en https://memories.ivjn.us Un token de miembro para ese servicio; la URL es fija

El modo Center de la aplicación significa un servidor con almacenamiento alojado habilitado (memories-center --data DIR). Es diferente de un Center de autorización que solo emite tickets y distribuye tickets firmados para dispositivos locales. Center y SaaS utilizan el mismo cliente alojado; difieren en la selección del endpoint y el perfil de conexión guardado. Ninguno exige crear o desbloquear primero una biblioteca local.

Primera conexión

  1. Seleccione un modo. La aplicación recuerda la elección para el siguiente inicio.
  2. Para Standalone, cree o desbloquee su biblioteca. Para Center, introduzca el origen HTTPS del servidor sin una ruta de API; para SaaS, conserve la dirección fija del servicio.
  3. En cualquiera de los modos alojados, introduzca el token de miembro proporcionado por el operador del servicio y elija Conectar. El rol y el ámbito del miembro determinan qué puede hacer; utilice un token de miembro para trabajar con contenido, no un token administrativo del operador.
  4. Después de conectar, abra Conocimiento alojado para explorar, buscar, ver, editar o eliminar conocimiento. También puede revisar solicitudes o abrir Dispositivos emparejados. La dirección del servidor, la bóveda actual y el ámbito concedido permanecen visibles.

El contenido alojado se cifra en reposo con una contraseña que conserva el operador, pero este puede leerlo. La aplicación muestra El servidor puede leer. Los secretos sellados entre dispositivos tienen un límite de protección de extremo a extremo separado.

Cambiar, desconectar y reconectar

Utilice Cambiar modo en la barra de herramientas principal antes o después de iniciar sesión. El diálogo marca el modo actual y explica el efecto; seleccione otro modo para cambiar o Cancelar para conservar la sesión. Termine o salga primero de un editor abierto; salir de un borrador sin guardar pide confirmación.

Acción Resultado
Cambiar modo Bloquea la biblioteca local, detiene la compartición, cierra la conexión alojada activa y borra el contenido visible; guarda el nuevo modo
Volver a Standalone Reabre la pantalla de la biblioteca local en estado bloqueado; los datos existentes permanecen
Entrar de nuevo en Center o SaaS Restaura la conexión guardada de ese modo cuando está disponible
Desconectar Elimina el token guardado del perfil actual y cierra su sesión; la URL y el perfil del otro modo permanecen
Pasar la aplicación a segundo plano Bloquea el acceso local, borra las sesiones alojadas y cierra las páginas y los borradores sensibles
Volver desde segundo plano Utilice Reconectar sesión guardada en la página alojada, o introduzca un token y vuelva a conectar

Cambiar de modo no carga, copia, combina ni elimina datos de bibliotecas. Desconectar no revoca el token en el servidor. Center y SaaS conservan sus pares URL/token en entradas separadas del almacenamiento seguro de la plataforma. Al actualizar, la conexión alojada antigua se importa solo al modo correspondiente; consulte configuración y migración.

Funciones disponibles

Flujo de trabajo Standalone Center / SaaS
Creación, copia de seguridad y restauración de bibliotecas locales Disponible Utilice el servicio alojado; no hace falta configuración local
Explorar, buscar, ver, editar y eliminar conocimiento Disponible tras desbloquear Conocimiento alojado, con acciones restringidas por el ámbito del token
Crear tarjetas de conocimiento Editor local de página completa Editor alojado de página completa con los campos aceptados por la API alojada
Revisar solicitudes alojadas de autorización Cambie a Center o SaaS Pestañas de pendientes/historial, confirmación de aprobación/rechazo y actualización
Emparejamiento de dispositivos Flujo local de aprobación de dispositivos/miembros Emparejamiento alojado, secretos sellados y controles de dispositivos, sujetos a permisos
Compartición por retransmisión y conexiones en la nube Disponible mediante los controles de la biblioteca local No se expone en la página alojada

La creación alojada omite etiquetas, fuente y relaciones; la edición de una tarjeta ordinaria existente admite estos campos y conserva otros metadatos. Las memorias ordinarias utilizan el editor de texto. Los perfiles estructurados, las tarjetas protegidas, las plantillas de tipos y las tarjetas E2E son de solo lectura en este editor general. Ambos editores conservan un borrador cuando falla el guardado; los borradores no persisten al bloquear la aplicación o pasarla a segundo plano. Consulte edición de contenido y autorización.

Solución de problemas de conexión

La aplicación valida los tokens mediante /v1/session antes de guardar una conexión, incluso para cuentas de solo escritura. Actualice los servidores propios junto con la aplicación. Las cuentas de solo lectura pueden explorar sin controles de modificación; las de solo escritura pueden crear sin cargar la biblioteca ni la lista de tipos. El servidor vuelve a autorizar cada operación. La búsqueda excluye contenido privado, credenciales y archivos; borre la consulta para volver a la lista de conocimiento. Las sesiones caducadas/revocadas, los permisos insuficientes y los servidores no disponibles tienen mensajes de error traducidos. Un 401 exige desconectar y conectar con un token válido.

  • No se puede conectar: compruebe el origen HTTPS completo, la red, el certificado y el token. Un Center propio debe habilitar el almacenamiento alojado; un servicio que solo emite tickets no puede proporcionar esta pantalla. localhost en un teléfono es el propio teléfono.
  • Permiso denegado: compruebe la bóveda, el rol, el ámbito y la caducidad del token con el operador del servicio. Seleccionar otro modo no concede acceso.
  • No hay solicitudes pendientes: actualice y compruebe el enrutamiento de solicitante/bóveda/aprobador. La pestaña de historial no es un registro de auditoría completo del servidor.
  • La sesión se cerró al pasar a segundo plano: reconecte explícitamente. Los borradores sin guardar se han cerrado como parte del bloqueo y no pueden restaurarse.
  • El servicio nativo no pudo iniciarse: utilice una compilación que contenga la biblioteca Rust correspondiente. Los modos alojados también utilizan FFI y requieren la biblioteca nativa.

Desarrollo

Compile primero las bibliotecas nativas con scripts/build-android.ps1 o scripts/build-ios.sh desde la raíz del repositorio. Consulte el README de la raíz para los requisitos de herramientas y las instrucciones de firma.

Utilice Flutter 3.44.2, como en CI. Desde este directorio:

flutter pub get
flutter gen-l10n
dart format --output=none --set-exit-if-changed lib test integration_test
flutter analyze
flutter test
flutter test integration_test/native_smoke_test.dart -d DEVICE_ID
flutter run -d DEVICE_ID

Las pruebas de widgets utilizan un backend simulado para ejercitar el ciclo de vida de la pantalla de bloqueo, la selección/cambio de modos, el aislamiento de sesiones alojadas, las tarjetas, la localización y los flujos de referencias secretas. Las pruebas de portapapeles simulan el canal de plataforma de Flutter; no verifican la entrega a un portapapeles del sistema operativo. La prueba de integración carga la biblioteca nativa real y crea una base de datos desechable en el dispositivo. Las ejecuciones normales utilizan el directorio de soporte de aplicaciones de la plataforma y un factor local protegido por Keychain/Keystore. Utilice datos de prueba durante el desarrollo; consulte SECURITY.md para los límites de confianza actuales.

Secretos de documentos y portapapeles

En modo Standalone, abra el menú de una memoria/tarjeta y elija Proteger secreto en el documento para sustituir un valor exacto de su cuerpo actual por una referencia con nombre. Confirme la advertencia sobre el historial, introduzca el nombre de la referencia y el secreto oculto y autorice cuando se le solicite. El servicio Rust almacena la credencial y sustituye el cuerpo en una sola transacción.

Elija Copiar secreto en un documento, tarjeta protegida o credencial para copiar su valor actual tras confirmar y autorizar. Los documentos muestran primero un selector de referencias. Las tarjetas OTP copian la semilla; su acción OTP separada genera un código de un solo uso. Los valores no se muestran y se descartan las respuestas tardías tras pasar a segundo plano o bloquear. Una copia completada en el portapapeles puede persistir después del bloqueo.

Las ediciones ordinarias conservan las asignaciones de referencias. Las versiones antiguas de documentos y las copias de seguridad existentes conservan su contenido anterior. Consulte la guía de secretos de la wiki para las reglas de referencias, actualizaciones, compatibilidad y límites del portapapeles. Recompile la biblioteca nativa junto con la aplicación Flutter al añadir estas operaciones.

Localización

Utilice el icono de idioma de la barra de la aplicación para seleccionar inglés, chino simplificado, japonés, alemán, francés o el idioma predeterminado del sistema. La preferencia se almacena separadamente de la biblioteca cifrada y está disponible mientras está bloqueada. Cambiar de idioma conserva la sesión actual de la biblioteca.

Las traducciones residen en lib/l10n/app_*.arb; flutter gen-l10n produce el directorio ignorado lib/l10n/generated/. Los controles Material y Cupertino utilizan los delegados de localización de Flutter. Siga la guía de localización al añadir mensajes o idiomas.

Compartir sesión (anfitrión RPC de retransmisión)

En modo Standalone, mientras está desbloqueado y en primer plano, el menú de opciones ofrece Compartir sesión. Se une a wss://…/v1/rpc/{room}/a con un token de alta entropía para que un CLI de escritorio pueda conectarse como slot b (MEMORIES_DAEMON_RELAY / MEMORIES_DAEMON_ROOM / MEMORIES_DAEMON_TOKEN). Pasar a segundo plano o bloquear detiene la sesión. No hay escucha HTTP/WS en móvil para el MVP; sigue aplicándose la lista de exclusión FFI nativa. Consulte daemon remoto.

Desbloqueo biométrico y acciones sensibles

En la biblioteca Standalone desbloqueada, utilice el menú de opciones → Desbloquear con biometría / bloqueo del dispositivo (desactivado por defecto; activarlo requiere una comprobación del sistema). lib/biometric.dart envuelve local_auth (BiometricPrompt en Android con alternativa de PIN/patrón/contraseña del dispositivo; Face ID / Touch ID en iOS, NSFaceIDUsageDescription en Info.plist). MainActivity extiende FlutterFragmentActivity como exige local_auth.

  • La contraseña de la biblioteca para el desbloqueo rápido se almacena con AndroidOptions.biometric(resetOnError: false): una clave AES de Android Keystore con setUserAuthenticationRequired(true) y setInvalidatedByBiometricEnrollment(true). En iOS, el elemento Keychain utiliza KeychainAccessibility.passcode.
  • Acciones sujetas a comprobación: desbloquear la biblioteca, copiar/revelar texto sin cifrar de credenciales, utilizar tarjetas protegidas / OTP, aprobar emparejamientos y solicitudes de Hosted Center, sellar y volver a sellar.
  • Cuando cambia la inscripción (KeyPermanentlyInvalidatedException), la aplicación informa al usuario, vuelve a verificar con la credencial del dispositivo, descarta solo la copia obsoleta de desbloqueo rápido y recrea la clave después de un desbloqueo por contraseña. La biblioteca nunca se borra.
  • Sin biometría/credencial de dispositivo, o con la opción desactivada: se utiliza el flujo existente de contraseña.
  • Las pruebas simulan DeviceAuth / UnlockSecretStore (test/biometric_test.dart).

Editor de contenido

lib/content_editor.dart se comparte entre nuevas memorias, credenciales y entradas de Hosted Center: importación de archivos (título a partir del nombre del archivo), modo monoespaciado para contenido similar a .env (detectado automáticamente o activado manualmente) y un nombre basado en el contenido que se infiere del nombre del archivo o de la primera línea no vacía y solo se solicita al guardar si sigue vacío. La escritura a mano (lápiz/borrador/deshacer/borrar, ML Kit Digital Ink) y el OCR (cámara/fotos/archivo, reconocimiento de texto de ML Kit) se ejecutan en el dispositivo; consulte escritura a mano y OCR. Las pruebas de widgets inyectan simulaciones de ScanServices.

Las memorias y tarjetas de conocimiento permanecen abiertas hasta que el guardado tiene éxito. Una escritura fallida conserva el borrador para reintentar; salir con cambios pide confirmación. Los borradores se mantienen solo en memoria y se cierran igualmente al bloquear por segundo plano o inactividad. La importación de archivos pregunta antes de sustituir texto existente. Las memorias exponen su ajuste privado/ordinario antes de guardar, y los reintentos de adjuntos omiten los archivos ya guardados durante la edición actual.

Las tarjetas de conocimiento utilizan un editor de página completa con una acción persistente de guardado, campos personalizados, etiquetas, fuentes y relaciones. Editar contenido abre el editor de texto compartido para importar archivos, escribir a mano y usar OCR. La creación alojada expone solo los metadatos aceptados por su API móvil existente.

Autorización en móvil

Las páginas Center y SaaS separan las solicitudes pendientes del historial. Revise el solicitante, la bóveda, el ámbito de acceso, la duración y el motivo completo antes de confirmar una aprobación o rechazo. La aprobación sigue utilizando el control existente de autenticación del dispositivo, y el solicitante debe reclamar la concesión por separado. Los errores conservan la solicitud para reintentar; tire para actualizar o utilice el botón de actualización.

La API de solicitudes de Center no devuelve un historial completo de decisiones. La pestaña de historial combina las decisiones tomadas durante la conexión actual con las solicitudes aprobadas devueltas por Center. Estos registros locales se borran al salir de la página. Las conexiones nuevas fallidas se cierran sin sustituir el perfil guardado.

La gestión local de miembros muestra solo acciones permitidas por los roles mostrados. Las confirmaciones identifican al miembro y el acceso anterior/nuevo. El servicio Rust vuelve a comprobar la política actual; el filtrado de la interfaz no concede ninguna autoridad. La pertenencia Owner no puede cambiarse mediante acciones ordinarias de roles, y solo los Owners ven la transferencia de propiedad.

Marca

Fuente del logotipo: assets/brand/logo.svg (+ logo-mono.svg, logo-foreground.svg adaptable). Los iconos y las imágenes de inicio se renderizaron con rsvg-convert; vuelva a generar los mismos tamaños cuando cambie el logotipo.