Files
fn_registry/functions/infra/matrix/matrix_crypto_init.md
T
egutierrez e22c33ee6d refactor(infra): split de drivers pesados a subpaquetes + fix TestSSEHandler
Mueve duckdb_open, clickhouse_open, postgres_open, matrix_* y keyring_token_store
del paquete monolitico functions/infra a subpaquetes propios
(functions/infra/{duckdb,clickhouse,postgres,matrix,keyring}). El paquete infra ya
no importa los drivers (go-duckdb, clickhouse-go, pgx, mautrix, go-keyring), por lo
que las apps que solo usan funciones ligeras (process, cron, http, sqlite) dejan de
arrastrarlos. Reduccion de binarios: dag_engine 72->10MB, registry_api 70->8.7MB,
services_api 70->9MB, call_monitor 68->6.6MB, sqlite_api 70->8.9MB.

Los IDs del registry se mantienen estables (domain: infra en frontmatter). Se
preservan los build tags goolm/libolm de matrix_crypto_init.

Tambien corrige TestSSEHandler: el test leia el body con un unico Read() que con
HTTP chunked solo capturaba el primer evento; ahora usa io.ReadAll hasta EOF.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 23:48:59 +02:00

5.6 KiB

name, kind, lang, domain, version, purity, signature, description, tags, params, output, uses_functions, uses_types, returns, returns_optional, error_type, imports, tested, tests, test_file_path, file_path
name kind lang domain version purity signature description tags params output uses_functions uses_types returns returns_optional error_type imports tested tests test_file_path file_path
matrix_crypto_init function go infra 0.1.0 impure func MatrixCryptoInit(ctx context.Context, cfg MatrixCryptoInitConfig) (*MatrixCryptoInitResult, error) Inicializa el crypto store Olm/Megolm para un *mautrix.Client usando cryptohelper v0.28+. Crea el SQLite store, carga la cuenta Olm, sube one-time keys al servidor y asigna client.Crypto para que SendMessageEvent cifre automaticamente en rooms E2EE.
matrix
mautrix
e2ee
olm
megolm
crypto
cryptohelper
infra
matrix-mas
name desc
ctx context.Context con deadline/cancel. Se propaga a helper.Init() que hace HTTP a Synapse. Usar timeout de al menos 5s (primera vez puede tardar ~500ms por /keys/upload).
name desc
cfg.Client *mautrix.Client ya inicializado via MatrixClientInit. Debe tener AccessToken, UserID y DeviceID poblados. DeviceID es obligatorio — descubrirlo via Whoami antes si no lo tienes.
name desc
cfg.StorePath Ruta absoluta al archivo SQLite del crypto store. Separado del state store. Si el directorio padre no existe, se crea con permisos 0700. Ejemplo: /home/lucas/.config/matrix_client_pc/egutierrez/crypto.db
name desc
cfg.PickleKey Exactamente 32 bytes usados para cifrar las sesiones Olm at-rest en el SQLite. Generar con crypto/rand.Read(). DEBE persistir entre arranques — guardar en keyring del sistema. Si se pierde, el store se vuelve inutilizable.
*MatrixCryptoInitResult con Helper (*cryptohelper.CryptoHelper ya asignado a client.Crypto y listo para Sync/SendMessageEvent) y StorePath (ruta al SQLite). Llamar helper.Close() en shutdown.
false error_go_core
maunium.net/go/mautrix
maunium.net/go/mautrix/crypto/cryptohelper
true
Client nil devuelve error
AccessToken vacio devuelve error
UserID vacio devuelve error
DeviceID vacio devuelve error
StorePath vacio devuelve error
StorePath relativo devuelve error
PickleKey != 32 bytes devuelve error
directorio del store se crea con permisos 0700
input valido Init exito helper no nil
Synapse 401 en keys upload devuelve error
functions/infra/matrix/matrix_crypto_init_test.go functions/infra/matrix/matrix_crypto_init.go

Ejemplo

import (
    "context"
    "crypto/rand"
    infra "fn-registry/functions/infra"
)

// Paso 1: cliente ya inicializado (ver matrix_client_init_go_infra)
clientRes, err := infra.MatrixClientInit(infra.MatrixClientInitConfig{
    HomeserverURL: "https://matrix-af2f3d.organic-machine.com",
    UserID:        "@egutierrez:matrix-af2f3d.organic-machine.com",
    AccessToken:   "mxat_xyz...",
    DeviceID:      "MYDEVICEID",
    StoreDir:      "/home/lucas/.config/matrix_client_pc/egutierrez/",
})
if err != nil { panic(err) }

// Paso 2: generar PickleKey (guardar en keyring, NO en codigo)
pickleKey := make([]byte, 32)
if _, err := rand.Read(pickleKey); err != nil { panic(err) }
// Persistir: secret-tool store --label="matrix pickle" service matrix account @user:server

// Paso 3: activar E2EE
ctx := context.Background()
cryptoRes, err := infra.MatrixCryptoInit(ctx, infra.MatrixCryptoInitConfig{
    Client:    clientRes.Client,
    StorePath: "/home/lucas/.config/matrix_client_pc/egutierrez/crypto.db",
    PickleKey: pickleKey,
})
if err != nil { panic(err) }
defer cryptoRes.Helper.Close()

// Ahora clientRes.Client.SendMessageEvent en rooms E2EE cifra automaticamente.
// El Syncer descifra mensajes recibidos tambien automaticamente.

Cuando usarla

Llamar UNA vez por sesion, tras MatrixClientInit y ANTES de arrancar client.Sync(). El orden es critico: si Sync arranca antes, los primeros eventos cifrados llegan sin handler Olm y se pierden. Una vez asignado client.Crypto, el Sync loop gestiona cifrado y descifrado transparente sin codigo adicional.

Gotchas

  • PickleKey DEBE sobrevivir entre arranques: si pierdes los 32 bytes, el store SQLite no se puede abrir y debes hacer nuevo login con nuevo DeviceID. Guardar obligatoriamente en keyring: secret-tool store --label="matrix pickle key" service matrix_client_pc account pickle_key_@egutierrez:servidor.
  • DeviceID es obligatorio: a diferencia de MatrixClientInit (que puede descubrirlo via Whoami), esta funcion falla si Client.DeviceID esta vacio para evitar crear un store huerfano vinculado a ningun dispositivo real.
  • StorePath debe ser persistente: NO usar /tmp/. Si el store se pierde entre arranques, se pierden las sesiones Olm — los mensajes historicos en rooms E2EE NO se podran descifrar sin Key Backup (issue 0150 full).
  • Init() hace HTTP a Synapse: primera vez ~500ms por /keys/upload. Usar context con timeout >= 5s. Si devuelve error con "M_UNKNOWN_TOKEN", el access token caducó — refrescar via OIDC.
  • Sin cross-signing/SAS: otros dispositivos ven el tuyo como "unverified" (amber warning en Element). E2EE sigue funcionando — cifra y descifra OK via TOFU. Cross-signing e implementacion de verificacion quedan para issue 0150 completo.
  • Build tag obligatorio: el archivo requiere -tags goolm (puro Go, sin CGO) o -tags libolm (CGO + libolm-dev instalado). Sin ninguno de los dos, el archivo no compila (build constraint).
  • client.Syncer debe ser ExtensibleSyncer: mautrix.DefaultSyncer lo implementa. Si usas Syncer custom, verificar que implementa mautrix.ExtensibleSyncer o NewCryptoHelper fallara.
  • Cerrar el helper en shutdown: helper.Close() cierra la conexion SQLite del store. Imprescindible para evitar WAL leak en el crypto.db.