Rama de desarrollo experimental sobre el Oasis de epsylon, sin afiliacion con el proyecto original. Base: 0.9.5. Trae el modulo Karvan —salas efimeras en memoria con autodestruccion por TTL, chat que funciona sin JavaScript y llamadas de audio y video sobre WebRTC— con el enlace en el menu lateral por el mismo patron que el resto de modulos: renderKarvanLink calcado de renderPollsLink, entrada en modules_view y en la lista de /modules. Los estilos del modulo van en su propia hoja, styles/karvan.css, siguiendo el patron de highlight.css: asi se ve igual con cualquier tema, sin depender del tema movil. Sin servidores ICE de terceros: no hay STUN de fabrica, porque un STUN aprende la IP publica y el momento de cada llamada. Solo candidatos host salvo que se configure un TURN propio en oasis-config.json, con credenciales efimeras por el mecanismo REST de coturn. El codigo propio vive separado —views/fork/, backend/fork_routes.js, models/karvan_model.js y translations/fork/— de modo que sobre los ficheros de upstream solo hay enganches de una linea y cada version nueva se integra sin arrastrar nada. Respecto al arbol de Android: fuera el wrapper y main.js, que es su arranque; el tema vuelve a Dark-SNH y se restauran los modulos que en movil se recortan por peso. Verificado arrancando sin OASIS_MOBILE: nueve rutas OK, menu lateral de upstream con 27 grupos y el enlace de Karvan, cero rastro de la interfaz movil (ni hexagonos, ni topbar, ni barra inferior), y una sala creada y servida.
12 KiB
1. Oasis a nivel de red (Secure Scuttlebutt)
Oasis es un cliente/servidor de Secure Scuttlebutt (SSB). Toda la "red" de
Oasis se construye sobre la pila clásica del ecosistema SSB:
secret-stack + ssb-db + un montón de plugins.
Hay una separación clara en dos procesos:
- Backend SSB (sbot) —
src/server/SSB_server.js: el nodo de red propiamente dicho. Es quien habla con otros peers. - Frontend web (GUI Koa) —
src/backend/backend.js: un servidor HTTP que actúa como cliente muxrpc del sbot, conectándose por un socket Unix local.
RED SSB (otros peers Oasis, misma SHS cap)
│
net:IP:8008~shs:<pubkey> · ssb-lan (UDP) · ssb-onion (Tor)
│
┌─────────────────────────────────────────────┐
│ SBOT (src/server/SSB_server.js) │
│ peer <-> MULTISERVER <-> SECRET-STACK (SHS) │
│ <-> MUXRPC <-> PLUGINS │
└─────────────────────────┬───────────────────┘
│ unix socket ~noauth (muxrpc local, sin SHS)
▼
┌─────────────────────────────────────────────┐
│ FRONTEND (src/backend/backend.js, Koa) │
│ cooler = src/client/gui.js → ssb-client │
│ app.listen({host, port:3000}) │
└─────────────────────────┬───────────────────┘
▼
Navegador http://localhost:3000
1.1 Arranque de red
Scripts de arranque
install.sh: instala Node 22 y hacenpm installensrc/server(línea 23). Opcionalmente descarga modelos de IA. No toca la red.oasis.shes el lanzador. Modos relevantes:server/pub(líneas 61-69): ejecutanode SSB_server.js start— solo el sbot headless, sin interfaz web.guio por defecto (líneas 73-81): ejecutanode backend.js— el frontend.- comandos pub
whoami|invite|name|announce|follow|status|gossip(líneas 70-72) → delegan enscripts/oasis-pub.js.
src/server/package.json, scriptstart:npm run start:ssb && sleep 10 && npm run start:backend. Arranca el sbot en segundo plano, espera 10 s (para que el socket Unix exista) y luego arranca el frontend.
Qué hace SSB_server.js paso a paso
(src/server/SSB_server.js)
- Líneas 7-11: carga
secret-stack,ssb-caps(la capability SHS),ssb-db, la config (./ssb_config) y utilidades de metadatos. - Líneas 13-52 (IIFE): monkey-patch de
console.error/console.warnpara silenciar ruido de red — rechazos de handshake por SHS cap incorrecta, excepciones EBT, etc. Un rechazo se convierte en un log limpio:[ts] REJECTED <ip:port> (wrong SHS cap). - Líneas 56-81: construye el servidor con
SecretStack({ caps }).use(plugin).use(plugin)...encadenando todos los plugins (ver tabla abajo). - Líneas 83-86: si no es pub, carga
ssb-lan(descubrimiento LAN por UDP) y el router LAN local./lanRouter. - Líneas 88-98: lógica de
autofollow; cargassb-autofollowsi hay feeds. - Líneas 123-196 (
argv[0] === 'start'): instancia el servidor, escribemanifest.json(el catálogo de métodos muxrpc remotos), monta una barra de progreso de replicación, imprime metadatos y escucha eventos del hub de conexiones (server.conn.hub().listen()) para loguearCONNECTED/DISCONNECTED. - Líneas 198-202: exporta
{ config, server, open() }— esto permite a la GUI reusar el servidor in-process si corre en el mismo proceso.
Plugins secret-stack cargados (líneas 56-98)
| Plugin | Función de red |
|---|---|
ssb-db |
base de datos append-only de feeds |
ssb-master |
identidad maestra / auth local |
ssb-gossip |
gossip clásico (legacy) de peers |
ssb-ebt |
Epidemic Broadcast Trees — replicación gossip eficiente |
ssb-friends |
grafo social: hops, follows/blocks |
ssb-blobs |
transferencia de ficheros binarios |
ssb-meme |
blobs de imágenes/memes |
ssb-conn |
gestor de conexiones moderno (hub, db, staging) |
ssb-box |
cifrado de mensajes privados (box1) |
ssb-search, ssb-private, ssb-friend-pub |
búsqueda, PM, pub de amigos |
ssb-invite / ssb-invite-client |
invites (servidor si es pub, cliente si no) |
ssb-replication-scheduler, ssb-partial-replication |
planificación de replicación |
ssb-onion |
transporte Tor |
ssb-unix-socket |
socket Unix local para clientes (la GUI) |
ssb-no-auth |
conexiones locales sin handshake SHS |
ssb-about, ssb-backlinks, ssb-links, ssb-tangle, ssb-query |
índices de vistas |
ssb-lan + lanRouter |
descubrimiento LAN (solo si no es pub) |
Nota: la replicación NO usa
ssb-replicatedirectamente; la orquestanssb-ebt+ssb-replication-scheduler+ssb-friends.
1.2 El protocolo SSB en términos del proyecto
-
secret-stack + handshake SHS (capability).
SecretStack({ caps })crea el nodo. Lacaps.shsestá fijada ensrc/configs/server-config.json(líneas 5-7):"H5EC+V5BU9s0lWxCkt4z8a095Sj8a6TgiLKPYi1JD7s=". Es la clave de capacidad de red (Secret Handshake): dos peers solo completan el handshake si comparten exactamente esta cap. Actúa como "contraseña de red": Oasis forma su propia red SSB privada, distinta de la red SSB pública. -
multiserver (transportes). Capa de transporte abstracta. La config
connections(server-config.json, líneas 29-60) define:- incoming.net:
transform: "shs",port: 8008→ TCP cifrado con SHS. - incoming.unix:
transform: "noauth"→ socket Unix local sin handshake, para que el frontend se conecte como cliente privilegiado. - outgoing.net:
transform: "shs". - Una dirección multiserver típica:
net:IP:8008~shs:<pubkey-base64>.
- incoming.net:
-
muxrpc (RPC sobre el stream). Una vez establecido el stream SHS,
muxrpcmultiplexa llamadas RPC asíncronas y pull-streams sobre la misma conexión. Elmanifest.jsondescribe qué métodos remotos existen (sync/async/source). Es como el frontend invocassb.publish(...),ssb.blobs.get(...), etc. -
EBT (
epidemic-broadcast-trees+ssb-ebt). El algoritmo de replicación gossip. Cada peer anuncia elseq(reloj vectorial) de los feeds que tiene; el otro envía solo los mensajes que faltan, formando árboles de difusión epidémica que evitan duplicados. -
Identidad de los peers. Cada peer es un feed id ed25519:
@<base64>.ed25519. En las direcciones multiserver, el sufijo~shs:<pubkey>identifica criptográficamente al peer durante el handshake.
1.3 Federación / P2P
-
Descubrimiento LAN (
src/server/lanRouter.js): plugin local custom.startRouter(líneas 55-64) arrancassb.lan.start()(broadcast UDP) y consumessb.lan.discoveredPeers(). Cada peer descubierto pasa porhandleDiscovery→stagePeer(líneas 15-45): lo stagea enssb.conn.stage(...)(vía moderna) con fallback assb.gossip.add(...)(legacy); sieagerReplicate, fuerzaebt.request. Respeta el flaglanBroadcastingdeoasis-config.json. -
Pubs / invites. En modo pub se carga
ssb-invite(servidor); en cliente,ssb-invite-client. Los comandosoasis.sh invite|announce|follow(→scripts/oasis-pub.js) permiten a un pub publicar su dirección y generar códigos de invitación. Un invite contienehost:port:pubkey~seed; al canjearlo, el peer se conecta y el pub le sigue de vuelta (ssb-friend-pub). -
Replicación por hops.
ssb-friendsdefine el grafo social.server-config.jsonfijafriends.hops: 2→ el nodo replica los feeds de la gente que sigues y de la gente que ellos siguen (amigos de amigos). Elssb-replication-schedulerdecide qué feeds pedir por EBT según ese grafo. -
"Distributed not decentralized". No hay servidor central ni DHT global. Cada nodo Oasis tiene su propia copia local de la base de datos (logs append-only firmados con ed25519) y solo replica los feeds dentro de su radio social (hops) más los descubiertos por LAN. La red se federa por gossip entre peers que comparten la misma SHS cap. Es distribuida (datos replicados en muchos nodos autónomos, funciona offline) pero no descentralizada como una blockchain (no hay consenso global ni vista única; cada quien ve solo su subgrafo). El flag
wishdeoasis-config.json(whole/mutuals/only-lan) controla el alcance de replicación deseado.
1.4 Puertos y endpoints
| Qué | Dónde | Puerto / dirección |
|---|---|---|
| muxrpc SSB (sbot) — otros peers se conectan aquí | server-config.json incoming.net |
8008/TCP transform shs |
| Socket Unix local — para el frontend | incoming.unix | unix:<ssb.path>/socket~noauth:<pubkey> |
| Frontend web (Koa) — tu navegador | oasis_client.js / middleware.js:180 |
3000 host localhost (configurable con --host/--port) |
Cómo se conecta el frontend al sbot (el "cooler", src/client/gui.js):
- Intenta
require('../server/SSB_server')y reusar elserverin-process si existe (sin socket, uso directo del objeto). - Si no, construye
remote = unix:<path>/socket~noauth:<pubkey>y se conecta conssb-client(muxrpc por el socket Unixnoauth). attemptConnectionWithBackoff: reintentos con backoff exponencial (de ahí elsleep 10del arranque).- Expone
cooler.open()/cooler.close(). Todos los modelos del backend reciben estecoolery hacenawait cooler.open()para obtener el cliente muxrpc.
Para exponer la GUI en un VPS se usa
--host=0.0.0.0.
1.5 Blobs (ficheros / imágenes)
- Plugin
ssb-blobs(+ssb-meme). Tamaño máximo enssb_config.js: 50 MB. - Un blob se referencia por hash:
&<sha256-base64>.sha256. Los mensajes del log solo llevan el hash, no el binario. - Flujo en
src/backend/blobHandler.js:- Subida:
ssbClient.blobs.add(...)recibe el contenido por pull-stream y devuelve el ref&...sha256. - Descarga por red:
blobs.has(id)comprueba si ya está local; si no,blobs.want(id)lo pide a los peers conectados (gossip de "want/has" sobre muxrpc), yblobs.get(id)lo lee como stream.
- Subida:
Los blobs viajan sobre la misma conexión SHS/muxrpc, fuera del log append-only.
1.6 Caps / cifrado
ssb-capsdefine las capabilities de protocolo (shs, sign, invite). La shs cap real está fijada enserver-config.json→ red privada de Oasis.- Handshake SHS: autenticación mutua por ed25519 + confidencialidad del stream de transporte.
ssb-box: cifrado de mensajes privados box1 (hasta ~7 destinatarios, cifrado por clave pública de cada feed).ssb-privateexpone publish/read.- Grupos privados ("tribes"). No se usa
box2/ssb-tribes. En su lugar Oasis implementa cifrado propio a nivel de aplicación ensrc/models/crypto.js, instanciado por dominio enbackend.js(tribeCrypto,chatCrypto,padCrypto,mapCrypto,calendarCrypto,eventCrypto,forumCrypto). Los grupos se cifran con esas claves derivadas y se almacenan/replican como mensajes normales del feed.
1.7 Archivos clave de la capa de red
| Archivo | Rol |
|---|---|
src/server/SSB_server.js |
Construye el sbot y carga los plugins (56-98) |
src/server/ssb_config.js |
Fusiona server-config.json; fija blobs.max=50MB |
src/server/ssb_metadata.js |
Deriva e imprime puerto SSB, hops, LAN, feed ID |
src/server/lanRouter.js |
Descubrimiento/staging de peers LAN |
src/configs/server-config.json |
caps.shs, pub, friends.hops, connections (puertos) |
src/configs/oasis-config.json |
lanBroadcasting, wish, pmVisibility, módulos |
src/client/gui.js |
El "cooler": cliente muxrpc por socket Unix noauth |
src/backend/blobHandler.js |
add/has/want/get de blobs |
scripts/oasis-pub.js |
Comandos pub (invite/announce/follow) |
Siguiente: 02-arquitectura-software.md.