167 lines
7.2 KiB
Text
167 lines
7.2 KiB
Text
===============================================================
|
|
CAMBIO TRAZABILIDAD DE INVITES
|
|
(commit 0fc10be)
|
|
===============================================================
|
|
|
|
PROBLEMA QUE RESUELVE:
|
|
El sistema original no tenia manera de saber:
|
|
- Quien genero un invite de tribe
|
|
- Cuando se uso un invite
|
|
- Quien uso el invite para entrar
|
|
Para pubs SSB, la aceptacion de invite no dejaba ningun rastro
|
|
en el log SSB propio.
|
|
|
|
--------------------------------------------------------------
|
|
PARTE 1 — TRIBE INVITES: inviteLog en tribes_model.js
|
|
--------------------------------------------------------------
|
|
ARCHIVO: src/models/tribes_model.js
|
|
|
|
ESTRUCTURA inviteLog (nueva):
|
|
Array de objetos almacenado en el contenido del mensaje SSB del tribe.
|
|
Cada entrada:
|
|
{
|
|
code: string (hex, 64 chars, el mismo que va en tribe.invites[])
|
|
generatedBy: string (SSB ID del usuario que genero el invite)
|
|
generatedAt: string (ISO 8601)
|
|
status: 'pending' | 'used'
|
|
usedBy: string | null (SSB ID del usuario que entro con el codigo)
|
|
usedAt: string | null (ISO 8601)
|
|
}
|
|
|
|
FUNCION generateInvite (linea 95):
|
|
- Genera code con: crypto.randomBytes(INVITE_CODE_BYTES).toString('hex')
|
|
- Lee el inviteLog actual del tribe (o [] si no existe)
|
|
- Añade nueva entrada con status 'pending', usedBy/usedAt null
|
|
- Guarda inviteLog junto al array invites (que ya existia)
|
|
- El array invites[] sigue existiendo tal cual para la logica de join
|
|
|
|
FUNCION joinByInvite (linea 132):
|
|
- Busca el tribe que tiene ese code en su invites[]
|
|
- Actualiza el inviteLog mapeando: si entry.code === code, marca
|
|
status 'used', usedBy = userId, usedAt = now
|
|
- Elimina el code de invites[] (el code queda consumido, no reutilizable)
|
|
- Guarda members, invites y inviteLog juntos en una sola llamada updateTribeById
|
|
|
|
FUNCIONES getTribeById / listAll:
|
|
Ambas ya exponían los campos del tribe. Se añadio:
|
|
inviteLog: Array.isArray(c.inviteLog) ? c.inviteLog : []
|
|
Si el tribe fue creado antes de este cambio, inviteLog sera [].
|
|
|
|
DONDE SE GUARDA ESTO:
|
|
El inviteLog se guarda en el contenido del mensaje SSB de actualizacion
|
|
del tribe (via updateTribeById que hace ssb.publish({type:'tribe', ...})).
|
|
Es decir, el log de invites esta en la blockchain SSB como parte del
|
|
historial del tribe. NOTA: si alguien lee el SSB log directamente,
|
|
vera el inviteLog serializado en el campo content del mensaje.
|
|
|
|
--------------------------------------------------------------
|
|
PARTE 2 — PUB INVITES: SSB message en main_models.js
|
|
--------------------------------------------------------------
|
|
ARCHIVO: src/models/main_models.js
|
|
|
|
PROBLEMA ORIGINAL:
|
|
ssb.invite.accept() es una llamada de bajo nivel del protocolo SSB.
|
|
Hace el handshake de red pero NO publica ningun mensaje en tu log propio.
|
|
No hay manera de saber despues que aceptaste ese pub invite.
|
|
|
|
SOLUCION:
|
|
Inmediatamente despues del handshake exitoso, publicar manualmente
|
|
un mensaje SSB en el log propio:
|
|
|
|
FUNCION acceptInvite (linea 722):
|
|
1. Convierte el invite string con toLegacyInvite()
|
|
2. Hace ssb.invite.accept(code, callback) — el handshake real
|
|
3. Parsea el code con parseRemote() para extraer host y pubId
|
|
(parseRemote ya existia en main_models.js, linea 119)
|
|
4. Publica: ssb.publish({ type: 'pub-invite', pubHost, pubKey, acceptedAt })
|
|
5. Devuelve el resultado del handshake
|
|
|
|
ESTRUCTURA del mensaje SSB publicado:
|
|
{
|
|
type: 'pub-invite'
|
|
pubHost: string | null (ej: 'pub.miservidor.net:8008')
|
|
pubKey: string | null (ej: '@xxxx.ed25519')
|
|
acceptedAt: string (ISO 8601)
|
|
}
|
|
|
|
Si parseRemote no puede extraer host o pubId, guarda null.
|
|
No rompe el flujo (el await del publish usa resolve() en ambos casos).
|
|
|
|
DONDE APARECE ESTO:
|
|
En el blockchain explorer, en el filtro 'invites',
|
|
y en cualquier lectura del SSB log propio.
|
|
|
|
--------------------------------------------------------------
|
|
PARTE 3 — BLOCKCHAIN EXPLORER: blockchain_model.js + blockchain_view.js
|
|
--------------------------------------------------------------
|
|
|
|
blockchain_model.js — filtro 'invites' (linea 209):
|
|
filtered = filtered.filter(b => b &&
|
|
(b.type === 'pub-invite' ||
|
|
(b.type === 'tribe' && Array.isArray(b.content?.inviteLog) && b.content.inviteLog.length > 0))
|
|
)
|
|
|
|
Muestra:
|
|
- Todos los mensajes SSB de tipo 'pub-invite'
|
|
- Todos los mensajes de tipo 'tribe' que tengan inviteLog con entradas
|
|
|
|
blockchain_view.js:
|
|
- FILTER_LABELS: 'pub-invite': 'PUB INVITE', invites: 'INVITES'
|
|
- CAT_BLOCK2: añadido 'invites' a la categoria de filtros secundarios
|
|
- TYPE_COLORS: verde (#27ae60) para pub-invite e invites
|
|
- getViewDetailsAction: case 'pub-invite' -> '/invites'
|
|
|
|
renderInviteExtra(block) — funcion nueva (linea 140):
|
|
Si block.type === 'pub-invite':
|
|
Tabla de 3 filas: PUB HOST | PUB KEY (user-link) | ACCEPTED AT
|
|
Si block.type === 'tribe' con inviteLog:
|
|
Tabla de 6 columnas:
|
|
CODE (primeros 12 chars + ...) |
|
|
GENERATED BY (user-link, primeros 16 chars) |
|
|
GENERATED AT |
|
|
STATUS (badge pending/used) |
|
|
USED BY (user-link) |
|
|
USED AT
|
|
Retorna null en cualquier otro caso.
|
|
|
|
Se llama dentro del render de cada bloque en la vista del explorer.
|
|
|
|
--------------------------------------------------------------
|
|
QUE PUEDE GUSTAR
|
|
--------------------------------------------------------------
|
|
- La trazabilidad de tribes es completa: sabes quien genero, cuando,
|
|
quien uso, cuando. Todo dentro del propio log SSB.
|
|
- Para pubs: al menos queda constancia en tu log propio de que
|
|
aceptaste ese pub invite y cuando.
|
|
- El inviteLog es retrocompatible: tribes viejas sin inviteLog
|
|
simplemente lo tienen como [].
|
|
- El code de tribe se elimina de invites[] al usarse (single-use).
|
|
- parseRemote ya existia y es la misma funcion que usa otro codigo
|
|
del modelo, no hay logica duplicada.
|
|
- Formato ISO 8601 para fechas, legible y ordenable.
|
|
|
|
--------------------------------------------------------------
|
|
QUE PUEDE NO GUSTAR / PUNTOS DE DISCUSION
|
|
--------------------------------------------------------------
|
|
1. El inviteLog se guarda en el mensaje SSB del tribe.
|
|
Esto significa que cada vez que alguien genera o usa un invite,
|
|
se publica un nuevo mensaje SSB de tipo 'tribe' con el inviteLog actualizado.
|
|
Si hay muchos invites, el historial de mensajes de la tribe crece.
|
|
No es un problema grave pero es algo a tener en cuenta.
|
|
|
|
2. El pub-invite SSB message lo publica DESPUES del handshake, no antes.
|
|
Si el proceso cae justo entre el handshake y el publish, el handshake
|
|
ocurre pero el log no se actualiza. Es una ventana de inconsistencia pequeña
|
|
pero existe.
|
|
|
|
3. El inviteLog esta en el contenido del tribe message, no en un tipo
|
|
de mensaje separado. Si alguien actualiza la tribe por otra razon
|
|
(cambio de descripcion, imagen...) y no incluye el inviteLog,
|
|
se perderia. Habria que revisar que updateTribeById siempre hace merge
|
|
de todos los campos del tribe, no solo los que se pasan.
|
|
|
|
4. El CODE en la tabla del blockchain se trunca a 12 chars.
|
|
Es solo visual. El code completo sigue en el dato y en invites[].
|
|
|
|
5. No hay manera de revocar un invite pendiente desde la UI.
|
|
Solo se "consumen" al usarse. Habria que anadir una accion de revocacion.
|