[0.9.1] FORK_IA_UX: Fase 2 cross-device — relay Karvan messages over SSB private msgs

Makes a Karvan room work between two different phones once they're connected to a pub:
- karvan_model: rooms track remoteFeeds (SSB ids of other participants); addRemoteFeed/
  getRemoteFeeds/anyRemoteRooms (feed-id validated, capped at MAX_MEMBERS).
- backend: inviting registers the invitee's feed; joining by link registers the inviter's
  feed (read from the invite PM). Posting a message publishes a private 'karvan-relay' to
  those feeds; an efficient LIVE log-stream subscriber (createLogStream old:false live:true)
  ingests incoming relays and injects them into the local mirror room (dedup by mid,
  skips own → no loop). WebRTC SIGNAL frames are NOT relayed (too many/slow for the log).
- Chosen over a muxrpc plugin because a classic pub only replicates the LOG (store-and-forward);
  live muxrpc wouldn't reach the other phone. No SSB-startup changes → no boot risk.
Verified: boot OK with the live stream, invite/adopt register feeds, message posts + relay
publishes, server stays up, 16/16 tests. Cross-device delivery needs the user's 2-phone+pub test.
Note: text chat only — video still needs the wrapper camera permission (Fase 3).
This commit is contained in:
s1to 2026-08-07 21:06:13 +02:00
parent 2c2c8f241d
commit 6020c7f8df
3 changed files with 90 additions and 2 deletions

View file

@ -166,6 +166,18 @@ async function test(name, fn) {
assert.ok(m.postSignal(r.id, { from: "a", to: "b", payload: { sdp: "small" } }), "payload pequeño pasa");
});
await test("feeds remotos: addRemoteFeed / getRemoteFeeds / anyRemoteRooms + validación", () => {
const m = makeModel();
const r = m.createRoom({});
assert.strictEqual(m.anyRemoteRooms(), false);
const feed = "@" + "A".repeat(43) + "=.ed25519";
assert.strictEqual(m.addRemoteFeed(r.id, feed), true);
assert.deepStrictEqual(m.getRemoteFeeds(r.id), [feed]);
assert.strictEqual(m.anyRemoteRooms(), true);
assert.strictEqual(m.addRemoteFeed(r.id, "no-es-feed"), false); // formato inválido
assert.strictEqual(m.addRemoteFeed("noexiste", feed), false); // sala inexistente
});
console.log("\n" + passed + " passed, " + failed + " failed");
process.exit(failed ? 1 : 0);
})();