docs: add detailed change documentation per feature phase
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ae7f0c1a4a
commit
07403d18c4
5 changed files with 717 additions and 84 deletions
167
CONTEXT/cambio_invites_trazabilidad.txt
Normal file
167
CONTEXT/cambio_invites_trazabilidad.txt
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
===============================================================
|
||||
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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue